![Java并发编程深度解析与实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/971/43737971/b_43737971.jpg)
1.7 线程的运行状态
线程从启动到最终销毁,整个生命周期会经历不同的状态,在Java中,线程一共有6种状态。
• NEW,新建状态,也就是调用new Thread()时的状态。
• RUNNABLE,运行状态,通过start()方法启动线程后的状态。
• BLOCKED,阻塞状态,当线程执行synchronized代码,并且未抢占到同步锁时,会变成该状态。
• WAITING,调用Object.wait()等方法,会让线程变成该状态。
• TIMED_WAITING,超时等待状态,如sleep(timeout),超时后会自动唤醒。
• TERMINATED,终止状态,线程的run()方法中的指令执行完成后的状态。
1.7.1 线程运行状态演示
在本节中主要演示线程状态的转化。
TIMED_WAITING状态
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-030-1.jpg?sign=1738811764-DcbvVJSdexzHvPB1nxQpJiewZqtbuWVa-0-bc02707ddf9b2cf54f619fce9473eb29)
上述代码运行后,使用jstack工具查看线程的dump信息,会看到如下内容,可以很明显地看到,通过sleep()方法阻塞的线程进入了TIMED_WAITING状态。
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-030-2.jpg?sign=1738811764-uvRzG3cxs7AG4XEF21KtcjsyiDz0XtH7-0-c0d8ea4ba49c4c0e9ef1a8c80f922407)
WAITING状态
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-031-1.jpg?sign=1738811764-PMXKHKRlZtHv8S9cyjom4KuFhzphZEed-0-e83f463a9875895e983ee1c0e284015f)
WAITING状态采用Object.wait()方法来实现,上述代码运行后,使用jstack工具查看到线程的dump日志,得到如下结果。
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-031-2.jpg?sign=1738811764-1cBCdQKWg2iUQTtSXdSMWfmWjACvTrQH-0-78334515b4e4e187ab346aa080e34594)
BLOCKED状态
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-031-3.jpg?sign=1738811764-dRlBQOoKuAR6SAb5oj2tTVr8bJn2xUwZ-0-3ab4f2a435f3de88b0e166bfc53c1614)
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-032-1.jpg?sign=1738811764-ce1qDIQG0XpXhHWaQi9uKamjPq7OOYHm-0-a49788472141d27e81e93e5f931359c8)
BLOCKED状态只有在synchronized锁阻塞时存在。上述代码创建了两个线程BLOCKED_T1和BLOCKED_T2来执行如下任务。
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-032-2.jpg?sign=1738811764-6GeODo655sIzVIMzaU5leVplqF8E8b58-0-506fcf4cda4a2f2a305cb38e388e7146)
了解这些状态有助于排查因CPU占用率较高导致的一些问题,后面会举案例来说明。
jstack工具使用方法如下。
• 打开终端命令,输入“jps”(显示当前所有Java进程pid)。
• 根据获取的pid可以打印指定Java进程ID的线程dump的信息。
1.7.2 线程运行状态流转图
图1-6表示Java线程的运行状态及触发状态变更的方法,该图对RUNNABLE状态进行了拆分描述,增加了CPU调度之前和调度之后的场景,实际上还是只有一种RUNNABLE状态。
![](https://epubservercos.yuewen.com/11B439/23020636309729206/epubprivate/OEBPS/Images/42136-00-033-01.jpg?sign=1738811764-RPU1WPEAhqHGmwUkPcLAsRh0gkqtyQAs-0-0ef547f45ec135460996cc2f705e7348)
图1-6 Java线程的运行状态及触发状态变更的方法