百色高端网站建设,有口碑的做网站,上海百网优seo优化公司,app开发公司天品科技目录 1.等待一个线程 join
2.休眠当前线程
3.线程的所有状态
4.线程的状态转换 1.等待一个线程 join 有些场景#xff0c;我们需要控制线程的执行顺序#xff0c;这时候就需要用到 join 了
比如#xff1a;把大象装进冰箱要几步#xff1f;
第一步#xff1a;打开冰… 目录 1.等待一个线程 join
2.休眠当前线程
3.线程的所有状态
4.线程的状态转换 1.等待一个线程 join 有些场景我们需要控制线程的执行顺序这时候就需要用到 join 了
比如把大象装进冰箱要几步
第一步打开冰箱
第二步把大象装进去
第三步把冰箱关上。 把每一步都当成一个线程来看那么线程2就要等线程1完成、线程3就等线程2完成。 public class Main {public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(()-{System.out.println(打开冰箱);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});Thread t2 new Thread(()-{System.out.println(把大象装进去);try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}});Thread t3 new Thread(()-{System.out.println(把冰箱关上);try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}});t1.start();t1.join();//main线程等待线程t1完成System.out.println(冰箱已经打开了);t2.start();t2.join();//main线程等待线程t2完成System.out.println(大象已经装进去了);t3.start();t3.join();//确保线程t3完成System.out.println(冰箱关上了任务完成);}
} 这里 start() 之后t1和 main 线程就开始并发执行了当 main 线程执行到 t1.join() 表示 main 线程得等 t1 线程执行完毕后才能接着往后执行代码只要 t1 线程没有执行完毕main 线程就会发生阻塞一直阻塞到 t1 线程执行完毕也就是执行完对应的 run 方法 像上述代码是可以等到 t1、t2、t3线程执行完毕了如果 t 线程执行的任务里面出现了死循环此时 main 线程不就无休止的等待了确实如此但是 join 给我们提供了一个带参数的方法等指定的时间到点就不等了 如下代码 public class Main {public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(()-{System.out.println(打开冰箱);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});Thread t2 new Thread(()-{System.out.println(把大象装进去);try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}});Thread t3 new Thread(()-{System.out.println(把冰箱关上);try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}});t1.start();t1.join(10000);//main线程等待线程t1完成System.out.println(冰箱已经打开了);t2.start();t2.join(10000);//main线程等待线程t2完成System.out.println(大象已经装进去了);t3.start();t3.join(10000);//确保线程t3完成System.out.println(冰箱关上了任务完成);}
} 把大象装进冰箱的三个步骤若是main线程等了10秒钟还没有完成该任务那么main线程就不等了10秒后冰箱门还不开就执行下一步了···· 还有一种情况 打开冰箱还需要10秒t1说我1秒就可以把冰箱打开了然后 main 线程执行 t1.join() 的时候但是 t1 线程的 run 方法已经执行完了此时 join 就不会阻塞了就会立即返回 2.休眠当前线程
休眠线程其实我们前面已经用了其本质就是让这个线程不参与调度了(不去 CPU 上执行)。
通过调用 Thread 类 中的 sleep 静态方法传入指定时间就能令线程休眠了。 注意哪个线程里调用 Thread.sleep(1000)就让哪个线程休眠 1000 毫秒 我们前面所说的 join 等待一个线程当 main线程 调用到 t.join() 时候main线程就要等待 t 线程 结束此时main线程就进入了阻塞状态
而现在所讲的sleep休眠当前线程也是进入阻塞状态 那么如何进入阻塞状态呢 在操作系统中有两个用于调度进程的重要队列阻塞队列和就绪队列 当线程 t1 调用 sleep() 方法就会进入阻塞队列当 sleep 结束就会进入就绪队列。 阻塞队列里的线程也就是暂时不参与 CPU 的调度了就绪队列中的线程随时可以被 CPU 调度 3.线程的所有状态 线程的状态是一个枚举类型Thread.State,我们可以打印出来看看都有哪些状态 public class Main {public static void main(String[] args) {for (Thread.State state : Thread.State.values()) {System.out.println(state);}}
} NEW: 安排了工作,还未开始行动,还没有调用 start 方法RUNNABLE: 可工作的又可以分成正在工作中和即将开始工作BLOCKED: 等待锁时产生的状态(锁竞争引起的阻塞)WAITING: 调用 wait 或 join 时进入的状态(死等引起的阻塞),TIMED_WAITING: 调用 sleep 进入的状态TERMINATED: 工作完成了 红标的状态都是阻塞状态只是引起阻塞的原因不同后面还会进行讲解 4.线程的状态转换
线程从创建到销毁期间会有一系列的状态变化如下图
下面我们通过代码来给大家演示一下线程的状态转换 public class Main {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {for (int i 0; i 10_0000; i) {}});System.out.println(start之前: t.getState());t.start();System.out.println(线程执行中的状态 : t.getState());Thread.sleep(1000);System.out.println(线程结束后的状态 : t.getState());}
} 当线程进入TERMINATED状态时也就是线程结束后线程所对应的PCB销毁了这时就无法重新启动线程重启就会抛出异常但是线程所对应的对象t还没有被回收我们仍然可以借助对象t来调用方法和属性只是无法通过多线程来干活了 接下来通过代码给大家演示一下线程 sleep 时候的 TIMED_WAITING 状态 public class Main {public static void main(String[] args) {final Object object new Object();Thread t new Thread(new Runnable() {Overridepublic void run() {synchronized(object) {while(true) {try{Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}}});t.start();} 上述代码用到了 synchronized 这里暂时不作解释将会在后续博客中进行讲解我们可以看到当我们的线程在循环执行 sleep 此时我们就可以通过 jconsole 工具来查看线程的状态该工具是jdk自带的可以在bin目录中找到有关于这个工具的讲解请看博主的上一篇博客 Thread类 的讲解如上图所示线程 sleep 后就进入了TIMED_WAITING的状态这个状态是线程在等待唤醒等到一定时间没醒就自动醒了 此时我们可以修改一下上述的代码把 t 中的 sleep 换成 wait 我们来看看线程状态的变化 public class Main {public static void main(String[] args) {final Object object new Object();Thread t new Thread(new Runnable() {Overridepublic void run() {synchronized(object) {while(true) {try{object.wait();
// Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}}}}});t.start();} 我们通过 jconsole工具看看此时线程的状态
如上图所示我们可以看到此时线程的状态就是WAITNG状态了WAITING状态是线程在无限等待唤醒若是没有唤醒这个线程那么这个线程就会一直等下去也就是我们所说的“死等” 由于BLOCKED状态涉及到了锁竞争这里暂时不作讲解大家了解一下即可这个状态是两个线程在争夺同一把锁引起的状态在后续博客中还会进行讲解 感谢观看希望对您有所帮助
下期预告线程安全