Thread线程状态
线程的状态及状态转换全解析
Java 线程的状态是并发编程的基础,JDK 官方(java.lang.Thread.State 枚举)定义了6种核心状态,状态转换则围绕“线程生命周期”和“同步/阻塞操作”展开。下面从「状态定义→转换规则→实战示例」讲透这一核心知识点。
一、先明确:Java 线程的 6 种核心状态
Thread.State 枚举明确了线程的所有合法状态,每个状态对应线程生命周期的一个阶段,先看官方定义:
| 状态名称 | 核心含义 |
|---|---|
NEW(新建) |
线程对象已创建,但未调用 start() 方法,未真正启动 |
RUNNABLE(可运行) |
线程调用 start() 后进入该状态(包含「正在运行」和「等待CPU调度」两种子状态) |
BLOCKED(阻塞) |
线程因竞争对象锁(如 synchronized)被阻塞,等待获取锁 |
WAITING(等待) |
线程无时限等待(需其他线程显式唤醒),如 Object.wait()、Thread.join() |
TIMED_WAITING(计时等待) |
线程有时间限制的等待,如 Thread.sleep(ms)、Object.wait(ms) |
TERMINATED(终止) |
线程执行完成(run() 方法结束)或异常终止,生命周期结束 |
注意:很多人会混淆「RUNNABLE 的子状态」—— RUNNABLE 包含“就绪(等待CPU)”和“运行(占用CPU)”,但 JDK 并未将其拆分为两个独立状态,统一归为 RUNNABLE。
二、核心:线程状态转换规则(附流程图)
线程的状态转换是“单向为主、部分双向”的,核心流转逻辑如下(用 Mermaid 可视化):

逐类拆解关键转换场景
1. NEW → RUNNABLE:唯一触发方式
只有调用线程的 start() 方法,才能让线程从“新建”进入“可运行”状态,且一个线程只能调用一次 start()(多次调用会抛出 IllegalThreadStateException)。
示例:
// NEW 状态:仅创建对象,未启动
Thread t = new Thread(() -> System.out.println("线程运行"));
System.out.println(t.getState()); // 输出:NEW
// 调用start(),进入RUNNABLE
t.start();
System.out.println(t.getState()); // 大概率输出:RUNNABLE(CPU调度可能有延迟)
2. RUNNABLE ↔ BLOCKED:仅与 synchronized 锁相关
只有竞争 synchronized 修饰的方法/代码块失败时,线程才会进入 BLOCKED 状态;一旦获取到锁,立即回到 RUNNABLE。
注意:
Lock锁(如ReentrantLock)的等待不会进入 BLOCKED 状态,而是进入 WAITING/TIMED_WAITING(因为Lock基于Condition实现,底层调用LockSupport.park())。
示例:
// 定义一个锁对象
Object lock = new Object();
// 线程1:先获取锁,持有5秒
Thread t1 = new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(5000); // 持有锁期间sleep,状态为TIMED_WAITING
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 线程2:竞争锁失败,进入BLOCKED状态
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("t2获取到锁");
}
});
t1.start();
Thread.sleep(100); // 确保t1先获取锁
t2.start();
Thread.sleep(100);
System.out.println(t1.getState()); // TIMED_WAITING(持有锁sleep)
System.out.println(t2.getState()); // BLOCKED(等待锁)
3. RUNNABLE → WAITING:无时限等待(需手动唤醒)
触发场景(核心3个):
- 调用
Object.wait()(需先持有对象锁,释放锁后进入等待); - 调用
Thread.join()(无参版,等待目标线程终止); - 调用
LockSupport.park()(无参版,底层支撑Lock锁)。
唤醒方式:
Object.wait()→ 其他线程调用Object.notify()/notifyAll()(需持有同一把锁);Thread.join()→ 目标线程执行完成;LockSupport.park()→ 其他线程调用LockSupport.unpark(线程对象)。
示例(wait/notify):
Object lock = new Object();
Thread t = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("进入WAITING状态");
lock.wait(); // 释放锁,进入WAITING
System.out.println("被唤醒,回到RUNNABLE");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // WAITING
// 主线程唤醒t
synchronized (lock) {
lock.notify();
}
4. RUNNABLE → TIMED_WAITING:有时限等待
触发场景(核心5个):
Thread.sleep(long ms)(最常用,不释放锁);Object.wait(long ms)(释放锁,超时自动唤醒);Thread.join(long ms)(超时自动退出等待);LockSupport.parkNanos(long ns);LockSupport.parkUntil(long deadline)。
唤醒方式:
- 超时自动唤醒(回到 RUNNABLE);
- 未超时被其他线程唤醒(如
notify()/unpark()); - 被中断(
interrupt()),抛出InterruptedException并回到 RUNNABLE。
示例(sleep 进入 TIMED_WAITING):
Thread t = new Thread(() -> {
try {
Thread.sleep(3000); // 进入TIMED_WAITING
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // TIMED_WAITING
5. 所有可运行状态 → TERMINATED:线程终止
线程进入 TERMINATED 的唯一原因:
run()方法正常执行完毕;- 运行过程中抛出未捕获的异常(如
NullPointerException),导致线程终止。
示例:
Thread t = new Thread(() -> {
System.out.println("线程执行中");
});
t.start();
Thread.sleep(1000); // 等待线程执行完成
System.out.println(t.getState()); // TERMINATED
三、易混淆点澄清
- BLOCKED vs WAITING/TIMED_WAITING:
- BLOCKED 仅针对
synchronized锁竞争; - WAITING/TIMED_WAITING 是主动调用等待方法(如
wait()/sleep())导致的等待。
- BLOCKED 仅针对
- sleep() 不释放锁,wait() 释放锁:
Thread.sleep()只是让线程暂停执行,不会释放已持有的synchronized锁;Object.wait()会立即释放持有的对象锁,等待被唤醒后需重新竞争锁。
- 中断对状态的影响:
- 对 WAITING/TIMED_WAITING 状态的线程调用
interrupt(),会抛出InterruptedException,并让线程回到 RUNNABLE 状态; - 中断不会直接终止线程,只是设置中断标志位,线程需自行检测并处理。
- 对 WAITING/TIMED_WAITING 状态的线程调用
总结
- 核心状态:Java 线程有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED 6 种状态,由
Thread.State枚举定义; - 核心转换:
- NEW 只能通过
start()进入 RUNNABLE; - RUNNABLE 因锁竞争进入 BLOCKED,获取锁后返回;
- RUNNABLE 因无时限/有时限等待进入 WAITING/TIMED_WAITING,唤醒/超时后返回;
- 所有可运行状态最终都会因执行完成/异常进入 TERMINATED;
- NEW 只能通过
- 关键区别:BLOCKED 仅与
synchronized锁相关,sleep()不释放锁,wait()释放锁。
百流积聚,江河是也;文若化风,可以砾石。

浙公网安备 33010602011771号