深入玩转JAVA多线程 Thread状态与生命周期

Posted 开普勒鑫球

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入玩转JAVA多线程 Thread状态与生命周期相关的知识,希望对你有一定的参考价值。


作者|开鑫金服-东东(DingXD)

编辑|Andy



Thread状态与生命周期


深入玩转JAVA多线程(一) Thread状态与生命周期

问题

一个thread在start执行完后,还能再次start吗?


thread.start();
TimeUnit.SECONDS.sleep(1);
thread.start();

连续调用两次start会异常

Exception in thread "main" java.lang.IllegalThreadStateException

原因是thread是有状态的,且有些状态之间的切换是不可逆的


动人 光荣

Thread的状态

 

深入玩转JAVA多线程(一) Thread状态与生命周期


1、新建状态(New):新创建一个线程对象的初始状态。

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于JVM可运行线程池中,变得可运行。该状态下线程等待操作系统调度,获取CPU的使用权后就可以执行线程代码。

3、阻塞状态(BLOCKED):线程在执行过程中,遇到被synchronized关键字保护的代码,等待获得被保护对象的锁(waiting for a monitor lock),此时线程会停止执行。

注意:只有synchronized这种方式的锁(monitor锁)才会让线程进入BLOCKED状态,等待利用cas实现的锁(如ReentrantLock)时,线程仍然处于Runnable状态。

4、等待状态(WAITING or TIMED_WAITING):

让线程进入WAITING只有一种方式:在同步块中,调用锁对象的wait方法,也会让当前持有锁的线程进入wait状态。

public static void timedWaiting() {

        final Object lock = new Object();

        synchronized (lock) {

            try {

                lock.wait();

            } catch (InterruptedException e) {

            }

        }

    }

让线程进入TIMED_WAITING状态,可以给wait方法加一个入参超时时间,或者直接调用线程的thread.join()方法。

处于WAITING状态的线程,只有其他线程调用了锁对象的notify方法才会执行。

处于TIMED_WAITING的线程,除了被锁对象的notify方法唤醒外,到了超时时间会自动唤醒(被join方法阻塞的线程不会被自动唤醒,因为在底层实现中超时时间被设置为0)。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。


深入玩转JAVA多线程(一) Thread状态与生命周期
BLOCKED和WAITING状态的区别

 

其实从字面意思就可以看出来:

blocked是过去分词,意思是线程在执行过程中被别人卡住了,即其他线程正在执行这段由synchd保护的代码,等别人执行完自己就会自动执行(jvm调度控制),不需要其他线程唤醒。

而waiting是主动执行wait动作后的当前状态,是主动卡住自己,必须由其他线程调用notify方法才能唤醒。

从下面代码可以方便的理解:

假设t1,t2先后两个线程,都执行如下代码:

synchronized(Obj{

    Obj.wait();

}

t1先进,最后在Obj.wait()下卡住,这时java管t1的状态waitting状态
t2后进,直接在第一行就卡住了,这时java叫t2为blocked状态。

 Java处于方便管理的考虑,将blocked和waiting状态的线程放到两个队列里(BlockSet和WaitSet),当别的线程运行出了synchronized这段代码,jvm只需要去BlockSet里取,当某人调用了notify(),jvm只需要从WaitSet里取,后面锁机制的章节会详细介绍。

所以两个状态的本质区别是进入和唤醒的条件不一样,其他没有任何区别。


动人 光荣

Thread生命周期



参考国外网站上一张图,个人认为画的最详细

深入玩转JAVA多线程(一) Thread状态与生命周期


注意:

1、  Waiting、Block、Runnable之间可以两两切换,而TERMINATED就是终态了,永远不可能在启动了。

2、  处于Runnable状态的线程,并不是立马就执行了,而是等待操作系统的调度启动。且线程再被CPU执行时也不是一口气执行到期,操作系统可能会将线程调出(比如有更高优先级的线程要处理),后续在调入,这个过程对于jvm是透明的。

 

 

敬请期待下一期人民最光荣

深入玩转JAVA多线程(二) 线程的属性与方法

参考

https://www.zhihu.com/question/27654579

https://blog.csdn.net/xionghan01/article/details/52840358

https://www.uml-diagrams.org/java-thread-uml-state-machine-diagram-example.html 


推荐阅读:

1、

2、

3、

4、

5、

6、


以上是关于深入玩转JAVA多线程 Thread状态与生命周期的主要内容,如果未能解决你的问题,请参考以下文章

从零开始的Java开发1-6-3 多线程:概念Thread类和Runnable接口创建线程线程的状态和生命周期sleep和join方法优先级同步线程间通信

java多线程的生命周期

Java线程生命周期及状态Java线程安全的的理解Thread与RunnableJava守护线程

Java中线程的生命周期

线程的生命周期(Java)

线程的生命周期(Java)