前言
在 Java 多线程编程中,线程的状态管理是理解并发逻辑的核心。本文将用通俗的语言和代码示例,解析线程的6种状态及其转换条件,助你彻底掌握线程的生命周期。
一、线程的6种状态
状态 | 含义 |
---|---|
NEW | 线程对象已创建,但未启动(未调用start() )。 |
RUNNABLE | 线程正在运行或就绪(等待 CPU 时间片),对应操作系统的“就绪态”和“运行态”。 |
BLOCKED | 线程因竞争锁(如 synchronized )被阻塞,直到获得锁。 |
WAITING | 无限期等待其他线程唤醒(如 wait() 、无参 join() )。 |
TIMED_WAITING | 有限期等待(如 sleep(ms) 、带超时的 join(ms) 。 |
TERMINATED | 线程已执行完毕,内核线程销毁,对象仍存在。 |
二、状态转换条件与场景
1. NEW → RUNNABLE
- 触发条件:调用
start()
方法。 - 代码示例:
Thread t = new Thread(() -> {}); // NEW
t.start(); // → RUNNABLE
2. RUNNABLE ↔ BLOCKED
触发条件:
- → BLOCKED:竞争
synchronized
锁失败。 - → RUNNABLE:成功获取锁。
示例场景:多线程访问同一同步代码块。
3. RUNNABLE ↔ WAITING
触发条件:
- → WAITING:调用
wait()
或join()
。 - → RUNNABLE:其他线程调用
notify()
/notifyAll()
或目标线程结束。 - 代码示例:
synchronized (lock) {
lock.wait(); // RUNNABLE → WAITING
}
4. RUNNABLE → TIMED_WAITING
触发条件:
- → TIMED_WAITING:调用
sleep(ms)
、join(ms)
或wait(ms)
。 - → RUNNABLE:超时结束或被
interrupt()
中断。
代码示例:
Thread.sleep(1000); // RUNNABLE → TIMED_WAITING
5. RUNNABLE → TERMINATED
触发条件:run()
方法执行完毕或抛出未捕获异常。
三、状态转换图
四、常见误区与注意事项
- RUNNABLE 包含“运行中”和“就绪”:
Java 不区分正在运行和等待CPU调度的线程,统一标记为 RUNNABLE。 - BLOCKED vs WAITING:
- BLOCKED:因锁竞争被阻塞(被动)。
- WAITING/TIMED_WAITING:主动调用等待方法(如
wait()
)。
sleep()
不释放锁:
线程休眠时仍持有锁(与wait()
不同,后者会释放锁)。
五、总结
- NEW 和 TERMINATED:线程的起点与终点。
- RUNNABLE:线程的活跃状态,可能正在运行或就绪。
- BLOCKED:锁竞争下的无奈等待。
- WAITING/TIMED_WAITING:主动让出 CPU,等待唤醒或超时。
理解线程转换,是诊断死锁、性能优化和设计高并发程序的基础。下次遇到线程“卡死”,不妨先看看它处于哪种状态!