哈喽,你们好,我是狗哥。很久没有更新原创文章了。主要是由于今年上半年这段时间都在忙着运营个人小号:上路的狗哥,主要分享一些职场以及生活中的高效又有趣的工具,好比:某度网盘提速工具、免费的 OCR 识别工具、免费听全网音乐的 APP 以及免费看全网影视的 APP 等等,感兴趣的能够关注一下。前端
通过半年的运营,小号在彻底零推广的状况下累计了 1.3W 铁粉。为何忽然又更新技术原创文章了?主要是由于写代码才是个人主业,公众号只是我的兴趣。作事不能本末倒置,因此决定之后仍是要周更这个技术公众号。java
人有生老病死。一样的,线程有本身的生命周期。在 Java 中线程的生命周期中一共有 6 种状态:面试
查看 Thread 类的源码时,内部还定义了这样一个枚举类。这个枚举类定义的就是线程的状态,源码以下:算法
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
PS:线程在任什么时候刻只可能处于以上 6 种的其中 1 种状态,咱们能够调用 getState() 查看线程的状态。数据库
咱们知道线程有 6 种状态。然而,它是如何切换的呢?狗哥根据本身的理解作了一张图,接下来将根据这张图详细了解下线程状态的切换。编程
先注意 NEW 状态:线程被 NEW 出来,但还没调用 start 方法时,就处于这种状态。一旦调用了 start 方法也就进入了 RUNNABLE 状态。设计模式
处于 RUNNABLE 的线程,比较特殊。它还分两种状态:Running 和 Ready。也就是说,Java 中处于 Runnable 状态的线程有可能正在执行,也有可能没有正在执行,正在等待被分配 CPU 资源。微信
所以,咱们能够推断出,一个处于 Runnable 状态的线程,当它运行到任务的一半时,执行该线程的 CPU 被调度去作其余事情,则该线程暂时不运行。可是,它的状态依然不变,仍是 Runnable,由于它有可能随时被调度回来继续执行任务。数据结构
也就是说:处于 Runnable 状态的线程并不必定在运行。这点在面试中常问,小伙伴们要注意了。并发
再来看看最简单的 Blocked 状态,从 Runnable 进入 Blocked 只有一种可能:就是进入 synchronized 关键字保护的代码,可是没有获取到 monitor 锁。
再来,看图的右侧,Blocked ----> Runnable 状态:当处于 Blocked 状态的线程获取到锁。
线程从 Runnable 进入 Blocked 状态,有三种可能性:
上面咱们知道,线程进入 Blocked 状态只多是:进入 synchronized 保护的代码,可是没获取到 monitor 锁。然而,Java 中还有不少锁,好比:ReentrantLock。线程在获取这种锁时,没有抢到就会进入 Waiting 状态,由于它本质上是调用了 LockSupport.park () 方法。
一样的,调用 Object.wait () 和 Thread.join () 也会让线程进入等待状态。
Blocked 与 Waiting 的区别是:Blocked 在等待其余线程释放 monitor 锁,而 Waiting 则是在等待某个条件,好比 join 的线程执行完毕,或者是 notify ()/notifyAll ()。
看 Waiting 右侧,Waiting ----> Runnable:一、当执行了 LockSupport.unpark (),二、join 的线程运行结束,三、被中断
看 Waiting 右侧,Waiting ----> Blocked:咱们看图能够知道其余线程调用 notify () 或 notifyAll () 来唤醒处于 Waiting 的线程,它会直接进入 Blocked 状态。这是为何?
其余线程能调用 notify () 或 notifyAll () 试图唤醒 Waiting 状态线程,说明必须持有同一个 monitor 锁,也就是说处于 Waiting 的线程被唤醒后并不能立刻抢到 monitor 锁,因此它必须先进入 Blocked 状态。而唤醒它的线程执行完毕释放锁后,它能抢到锁就从 Blocked 进入 Runnable 状态。
这种状态与 Waiting 状态的区别在于:有没有时间限制,Timed Waiting 会等待超时,由系统自动唤醒,或者在超时前被唤醒信号唤醒。
有如下 5 种状况会让线程进入 Timed Waiting 状态:
看 Timed Waiting 右侧,Timed Waiting ----> Blocked:跟 Waiting 同样,其余线程执行 notify () 和 notifyAll (),当前线程也是先进入 Blocked 状态,然后视锁的获取状况再决定是否进入 Runnable 状态。
另外,Timed Waiting ----> Runnable :一、当前线程的超时时间到了且能直接获取到锁,二、join 的线程运行结束,三、被中断,四、调用了 LockSupport.unpark (),这几种状况会直接恢复到 Runnable,而无需经历 Blocked 状态。
最后一种,想要进入终止状态就比较简单了,有三种状况:
若是看到这里,喜欢这篇文章的话,请帮点个好看。微信搜索一个优秀的废人,关注后回复电子书送你 100+ 本编程电子书 ,不仅 Java 哦,详情看下图。回复 1024送你一套完整的 java 视频教程。