线程一共6 种状态。线程在生命周期内,会随着代码执行、锁竞争、等待操作,在不同状态之间切换。注意:Java 线程状态和操作系统内核线程状态不是完全等同的,我们这里讨论的是 Java 虚拟机层面定义的线程状态。
1. 线程的总数量和含义
在 Java 中,线程的状态由枚举类java.lang.Thread.State定义,线程一共存在 6 种状态,分别是:
- NEW(新建)
- RUNNABLE(可运行)
- BLOCKED(阻塞)
- WAITING(无限等待)
- TIMED_WAITING(限时等待)
- TERMINATED(终止)
只要线程状态不是 NEW 和 TERMINATED,线程都属于存活状态(isAlive() == true)。
1.1NEW 新建状态
线程对象刚刚new创建出来,任务已安排,但还没有调用start()方法,线程没有真正启动。 通俗理解:工作已经安排好,但是还没有开始行动。
1.2RUNNABLE 可运行状态
调用start()方法后进入该状态。 该状态包含两种情况:
- 即将开始工作(就绪状态 READY)
- 正在工作中(运行状态 RUNNING) 通俗理解:线程随时可以被 CPU 执行,正在排队或者正在运行。
1.3 BLOCKED 阻塞状态
线程等待获取 synchronized 同步锁时的状态。 当线程想执行同步代码块 /同步方法,但是锁被其他线程占用,当前线程就会进入阻塞状态,直到获取到锁。 通俗理解:排队等待别人释放锁资源。
1.4 WAITING 无限等待状态
线程主动进入无期限等待,需要被其他线程唤醒,否则一直等待。 进入条件:调用wait()、join()、LockSupport.park()。 通俗理解:原地等待,不主动苏醒,必须别人通知。
1.5 TIMED_WAITING 限时等待状态
带时间限制的等待状态,等待时间结束自动唤醒,也可以被提前唤醒。 进入条件:调用sleep(时间)、wait(时间)、join(时间)。 通俗理解:等待一段时间,时间到了自动继续执行。
1.6 TERMINATED 终止状态
线程任务执行完毕,或者出现异常结束,线程生命周期彻底结束。 处于该状态的线程无法再次启动。 通俗理解:工作全部完成,线程结束。
2. 线程状态切换条件(完整流转)
- NEW → RUNNABLE调用线程的
start()方法,线程正式启动。 - RUNNABLE ↔ BLOCKEDRUNNABLE → BLOCKED:线程竞争
synchronized锁失败,锁被占用。 BLOCKED → RUNNABLE:线程成功获取到同步锁。 - RUNNABLE ↔ WAITINGRUNNABLE → WAITING:执行
wait()、join()等方法。 WAITING → RUNNABLE:被其他线程notify()/notifyAll()唤醒或等待线程结束。 - RUNNABLE ↔ TIMED_WAITINGRUNNABLE → TIMED_WAITING:执行
sleep()、带超时的wait()/join()。 TIMED_WAITING → RUNNABLE:等待时间超时,或被提前唤醒。 - RUNNABLE → TERMINATED线程任务执行完毕,或运行中出现异常,线程终止。
3. 代码示例
3.1 观察 1:NEW、RUNNABLE、TERMINATED 基础状态转换
public class ThreadStateTransfer { public static void main(String[] args)throws InterruptedException { Thread t=new Thread(()->{ for (int i = 0; i < 100_000; i++) { //空循环,消耗CPU } },"李四"); //NEW状态 System.out.println(t.getName()+':'+t.getState()); t.start(); //线程存货时循环打印状态 while (t.isAlive()){ System.out.println(t.getName()+':'+t.getState()); } //TERMINATED状态 System.out.println(t.getName()+':'+t.getState()); } }运行结果:
new Thread()之后,线程状态为NEW;- 调用
start()后变为RUNNABLE; - 循环执行结束,线程进入
TERMINATED。
3.2 观察 2:BLOCKED、WAITING、TIMED_WAITING 状态转换
public class ThreadStateDemo2 { public static void main(String[] args) { final Object object=new Object(); Thread t1=new Thread(new Runnable() { @Override public void run() { synchronized (object){ try { // Thread.sleep(1000); // 打开这行:t1状态 TIMED_WAITING object.wait(); // 打开这行:t1状态 WAITING } catch (InterruptedException e) { e.printStackTrace(); } } } },"t1"); t1.start(); Thread t2=new Thread(new Runnable() { @Override public void run() { synchronized (object){ System.out.println("hehe"); } } },"t2"); t2.start(); } }运行结果:
- 当
t1执行Thread.sleep(1000),使用jconsole观察,t1 状态为TIMED_WAITING;t2 抢不到锁,状态为BLOCKED。 - 修改代码,把 sleep 换成
object.wait(),t1 状态变为WAITING,t2 依旧是BLOCKED。
结论:BLOCKED 表示等待获取锁;WAITING 和 TIMED_WAITING 表示等待其他线程发来通知。TIMED_WAITING 线程在等待唤醒,但设置了时限;WAITING 线程在无限等待唤醒。
4.总结
- Java 线程一共6 种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
- RUNNABLE 包含就绪和运行两种子状态。
- BLOCKED 是等待 synchronized 锁,WAITING/TIMED_WAITING 是等待其他线程通知。
- 线程终止后不可重启;只有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING 属于存活状态。