只要开启线程,都会开启一块对应的栈内存,然后进行同步执行. -- 谈斌
线程是CPU用来处理程序的资源,线程的执行是抢占式的.
线程开启方式:
-
创建一个类,继承Thread类.
重写 run(), 并在run方法内编写线程需要执行的内容创建
/* * 线程开启方式1: * 1.创建一个类,继承Thread类. * 2.重写 run(), 并在run方法内编写线程需要执行的内容 * */ public class MyThread extends Thread { // 构造方法 public MyThread() { super(); } public MyThread(String name) { super(name); } // run方法里面写的是线程需要执行的内容 @Override public void run() { for (int i = 0; i < 100; i++) { // 让线程睡2秒 try { Thread.sleep(2000); } catch (InterruptedException e) { // 中途打断的意思 // 输出异常的 名称,信息,位置 e.printStackTrace(); } System.out.println(getName()+"I Love Java"); } } } /* * Runnable接口应该是被封装了开启cpu线程的C语言方法 * */
开启/* * 线程对象只能是 * Thread类的对象或者是Thread类的子类对象 * * 线程体系结构: * 根节点: Runnable()接口 --> 抽象方法run() * 实现类: Thread类 * 想在执行线程任务的时候,带上线程名称: * String getName(): 获取线程名称 * --> 直接调用getName()方法只能在Thread的子类中调用 * * 想在执行任务的时候打印主线程的名称:(因为ThreadDemo01类不是Thread的子类) * Thread类中有: * static Thread currentThread():获取当前线程对象 * void setName(String name):对线程对象的名字进行设置 * static void sleep(long millis):让线程睡觉,睡多久: long millis决定 * */ public class ThreadDemo01 { public static void main(String[] args) throws InterruptedException { // 创建线程对象 MyThread mt = new MyThread(); // 启动线程 mt.start(); // run方法是由start方法帮忙调用的 for (int i = 0; i < 100; i++) { Thread.sleep(3000); System.out.println(Thread.currentThread().getName()+"I Love C^_^"); } } }
- (把任务和线程分离) --> 推荐
创建一个类, 实现Runnable接口
并在这个类中重写run(), 写入线程需要执行的任务创建
/* * 第二种线程开启方式: (把任务和线程分离) --> 推荐 * 1. 创建一个类, 实现Runnable接口 * 2. 并在这个类中重写run(), 写入线程需要执行的任务 * */ public class Target implements Runnable { @Override public void run() { for (int i = 0; i < 50; i++) { System.out.println(Thread.currentThread().getName() + ": Hello World !"); } } }
开启public class ThreadDemo02 { public static void main(String[] args) { // 创建线程的任务对象 Target target = new Target(); // 任务 Thread t0 = new Thread(target); // 雇佣兵 // 设置线程名称 t0.setName("stark"); t0.start(); Thread t1 = new Thread(target); // 另一个雇佣兵 // 两个雇佣兵在做相同的任务 t1.setName("spider"); t1.start(); // 匿名内部类开启线程方式,相当于开启方法一 Thread t2 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 50; i++) { System.out.println(Thread.currentThread().getName()+": biu biu biu~"); } } }); t2.setName("captain"); t2.start(); } }
我并不明白匿名内部类开启线程的方式算不算一种新的开启方式,你觉得呢?
线程安全问题 : 线程的抢占式执行机制, 造成了执行中出现的各种我们不想看到的问题.
应对策略: 1.synchronized()
2.Lock 锁
/* * 同步代码块: * synchronized(锁对象) { * 你需要上锁(同步)的代码 * } * 任意引用类型的对象,这个锁对象必须被所有的任务对象共享 * * 总结: * 同步:当一个线程正在执行任务的时候,不让其他线程进入!! * 同步提高了代码的安全性,但是降低了代码的效率 * */ public class SellTicket implements Runnable{ // 成员变量 int ticket = 100; /* * synchronized 里面可以放 Integer 却不能放 int 变量 * 这也许就是包装类吧 * */ Integer tic = new Integer(ticket); // 锁对象 --> 你请人帮你看门 Object obj = new Object(); @Override public void run() { // 电影院不关门 while (true) { synchronized (this) {// 你进了厕所把门关了 if (ticket > 0) { // 每半秒钟卖一张票 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } // 窗口名 + “卖了第” +ticket+ “张票~” System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票~"); ticket--; } } } } /* * 同步方法 --> 被 synchronized 修饰的方法 * 锁对象 this * * 静态同步方法 --> 锁对象: 类的字节码对象! * */ // public synchronized void sell() { // if (ticket > 0) { // // 每半秒钟卖一张票 // try { // Thread.sleep(500); // } catch (InterruptedException e) { // e.printStackTrace(); // } // // 窗口名 + “卖了第” +ticket+ “张票~” // System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票~"); // ticket--; // } // } }
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* * Lock 锁的使用步骤: * 1. 创建锁对象: * Lock lock = new ReentrantLock(); * 2. 在需要上锁的代码前面 上锁! --> lock.lock() * */ public class SellTicket01 implements Runnable { // 成员变量 int ticket = 100; /* * synchronized 里面可以放 Integer 却不能放 int 变量 * 这也许就是包装类吧 * */ Integer tic = new Integer(ticket); // 创建锁对象 Lock lock = new ReentrantLock(); @Override public void run() { // 电影院不关门 while (true) { lock.lock(); if (ticket > 0) { try { // 每半秒钟卖一张票 Thread.sleep(500); // 窗口名 + “卖了第” +ticket+ “张票~” System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票~"); ticket--; } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } } }
最后附上线程的生老病死图, 希望大家月薪过万的时刻指日可待 ^^