Java线程有六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED;NEW需调用start()进入RUNNABLE,RUNNABLE包含就绪与运行,BLOCKED由锁竞争引起,WAITING为无限期等待唤醒,TIMED_WAITING带超时自动恢复,TERMINATED为终态不可逆。

Java 线程的生命周期由 java.lang.Thread.State 枚举定义,共 6 种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。这些状态不是随意跳转的,每种切换都对应明确的代码动作或系统条件。
NEW → RUNNABLE:必须调用 start() 才算真正“启动”
线程对象刚用 new Thread() 创建时,只是普通 Java 对象,处于 NEW 状态。它还没和操作系统线程绑定,也不能执行任何逻辑。
- 只有显式调用
thread.start(),JVM 才会向操作系统申请资源、创建底层线程,并将状态设为 RUNNABLE - 直接调用
run()方法不会改变状态,仍是 NEW(或调用后立即结束),也**不开启新线程** - start() 只能调用一次;重复调用抛出
IllegalThreadStateException
RUNNABLE 是“可调度态”,不等于“正在运行”
RUNNABLE 包含两个实际场景:就绪(Ready,排队等 CPU)和运行(Running,正在执行)。JVM 统一抽象为 RUNNABLE,因为用户代码无法感知调度细节。
- 线程进入 RUNNABLE 后,可能立刻执行,也可能等待几毫秒甚至更久——取决于 CPU 负载和调度策略
- 主动让出 CPU(如
Thread.yield())不会退出 RUNNABLE,只是从 Running 回到 Ready - I/O、锁竞争失败、sleep 等操作都会导致它离开 RUNNABLE,进入其他阻塞/等待态
BLOCKED、WAITING、TIMED_WAITING:三类“暂停”,原因不同
这三种状态的共同点是:线程不参与 CPU 竞争,不消耗 CPU 时间片。但触发机制和唤醒方式有本质区别:
立即学习“Java免费学习笔记(深入)”;
-
BLOCKED:只因抢不到
synchronized锁。比如线程 A 持有对象锁,线程 B 尝试进入其同步块,就会卡在 BLOCKED,直到 A 释放锁 -
WAITING:调用无超时参数的方法,必须靠别人“叫醒”。例如:
obj.wait()、thread.join()、LockSupport.park() -
TIMED_WAITING:自带倒计时,时间到自动恢复,也可被提前唤醒。常见于:
Thread.sleep(1000)、obj.wait(500)、thread.join(2000)
回到 RUNNABLE 或终结:唤醒与完成
从等待或阻塞中恢复,核心在于“谁来触发”和“是否可控”:
- BLOCKED → RUNNABLE:持有锁的线程退出同步块或抛出异常,锁自动释放
- WAITING → RUNNABLE:必须由其他线程调用
notify()/notifyAll(),或中断该线程(interrupt()) - TIMED_WAITING → RUNNABLE:超时自动触发,或被
notify()/interrupt()提前唤醒 - RUNNABLE → TERMINATED:run() 方法自然结束,或抛出未捕获异常;一旦进入 TERMINATED,状态不可逆,不能再 restart
理解的关键不是死记状态名,而是抓住每个状态背后的资源约束:NEW 没线程资源,RUNNABLE 等 CPU,BLOCKED 卡在锁,WAITING/TIMED_WAITING 卡在协作信号。状态图只是表象,背后是 JVM 对操作系统原语的封装与抽象。


















