new→runnable的唯一触发条件是调用start();runnable表示具备运行资格而非正在执行;blocked、waiting、timed_waiting均为阻塞态但原因不同;terminated仅由run()结束或未捕获异常导致,不可逆。

NEW → RUNNABLE 的触发条件
线程对象刚用 new Thread() 创建完,还没调用 start(),它就处于 NEW 状态。只有显式调用 start() 后,JVM 才真正为其分配资源、启动执行引擎,状态才变为 RUNNABLE。
注意:start() 不能重复调用,否则抛出 IllegalThreadStateException;也不可直接调用 run() —— 那只是普通方法调用,不会触发状态切换,线程仍卡在 NEW(实际是根本没进入生命周期)。
-
start()是唯一合法的“启动入口” - 线程池中提交的
Runnable,由 Worker 线程执行,其内部仍是通过start()(或复用已启动线程)进入RUNNABLE - 从
NEW到RUNNABLE是单向、不可逆的起点
RUNNABLE 和 BLOCKED / WAITING / TIMED_WAITING 的区别
RUNNABLE 不等于“正在 CPU 上运行”,它表示线程具备运行资格:可能正执行、可能在就绪队列排队、也可能被 OS 调度挂起。而 BLOCKED、WAITING、TIMED_WAITING 都属于“非运行中”的阻塞态,但阻塞原因不同:
-
BLOCKED:试图进入synchronized块/方法,但锁被其他线程持有(等待 monitor entry) -
WAITING:调用Object.wait()、Thread.join()、LockSupport.park()且未设超时 -
TIMED_WAITING:调用带超时的wait(long)、sleep(long)、join(long)、parkNanos()等
关键点:从 RUNNABLE 进入这三种状态,都是主动让出 CPU,且需外部事件唤醒(锁释放、notify、中断、超时等)。它们之间无法直接跳转 —— 比如 WAITING 线程被 interrupt() 后,会先抛出 InterruptedException,然后回到 RUNNABLE,而不是变成 TIMED_WAITING。
TERMINATED 状态不是“自然终点”
线程进入 TERMINATED 只有一种方式:对应任务彻底结束 —— 即 run() 方法正常 return,或抛出未捕获异常终止。它不可逆,也不能重用。
常见误解:
-
stop()已废弃,强制终止会破坏锁一致性,绝不可用 -
interrupt()不会直接让线程变TERMINATED,它只是设置中断标志,线程需自行检查并退出(比如在循环中判断Thread.interrupted()) - 线程池中的线程被“回收”,其实是回到空闲状态(
RUNNABLE等待新任务),不是TERMINATED
所以,别指望靠中断或外部信号“切换到 TERMINATED”,那是业务逻辑该负责的事。
状态切换不反映真实调度细节
JVM 线程状态是抽象层视图,和 OS 线程状态不一一映射。例如:
-
RUNNABLE下的线程可能正被 OS 调度为休眠(如因 I/O 等待陷入内核态),但 JVM 仍报RUNNABLE -
WAITING中的线程若被interrupt(),状态会立即变为RUNNABLE,但实际恢复执行还要等调度器分配时间片 - 某些 JVM 实现(如 Zing)甚至将
BLOCKED细化为更精确的锁竞争状态,但标准 API 仍只暴露这六种
调试时用 Thread.getState() 或 jstack 看到的状态,只能帮你定位大致卡点,不能替代系统级 trace 工具(如 async-profiler)分析真实阻塞根源。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










