调用start()是new→runnable的唯一合法转换,触发jvm分配资源并注册调度;runnable表示已就绪但未必正在执行,后续状态变迁由代码行为和os调度共同决定,terminated不可逆。

调用 Thread.start() 并不会立即执行 run() 方法,而是触发 JVM 对线程生命周期的正式管理,其背后是一系列明确、受控的状态变迁。
NEW → RUNNABLE:start() 的核心作用
start() 方法本质是向 JVM 发起“启动线程”的请求。此时线程从 NEW 状态(刚 new 出来、尚未调度)转变为 RUNNABLE 状态——注意,这不是“正在运行”,而是“已就绪,等待 CPU 调度执行”。JVM 会为该线程分配程序计数器、Java 虚拟机栈、本地方法栈等资源,并将其加入操作系统线程调度队列。
- 调用
start()后,线程对象的isAlive()立即返回 true - 重复调用
start()会抛出IllegalThreadStateException - 直接调用
run()不会改变线程状态,它只是普通方法调用,仍在当前线程中执行
RUNNABLE → RUNNING:由 OS 调度决定
RUNNABLE 是 JVM 定义的状态,RUNNING 是操作系统层面的实际执行状态。当 OS 调度器选中该线程并分配 CPU 时间片后,线程才真正开始执行 run() 中的代码,进入“运行中”阶段。这个过程对 Java 程序员透明,无法通过 API 直接观测到 RUNNING(JVM 状态枚举中没有 RUNNING)。
- JVM 的
Thread.State枚举里没有 RUNNING,只有 RUNNABLE、BLOCKED、WAITING 等 - 线程在 RUNNABLE 状态下可能因未获 CPU 而暂停,也可能正在执行——两者都算 RUNNABLE
- 是否立刻执行取决于系统负载、优先级、调度策略,
start()不保证立即运行
RUNNABLE → 其他状态:后续自然演进
一旦线程开始执行 run(),其状态将根据代码行为动态变化:
- 遇到
synchronized锁且锁被占用 → 进入 BLOCKED - 调用
Object.wait()、Thread.join()或LockSupport.park()→ 进入 WAITING 或 TIMED_WAITING -
run()正常结束或抛出未捕获异常 → 进入 TERMINATED - 调用
Thread.sleep()→ 进入 TIMED_WAITING
状态不可逆:TERMINATED 后无法重启
线程一旦到达 TERMINATED 状态(执行完毕或异常终止),其状态永远不会再变回 RUNNABLE 或其他活跃状态。尝试再次调用 start() 会抛出异常;也无法复用该线程对象。必须新建 Thread 实例才能开启新执行流。
- 线程生命周期是单向的:NEW → RUNNABLE → (BLOCKED/WAITING/TIMED_WAITING) → TERMINATED
- 没有 STOP、SUSPEND、RESUME 等已废弃状态,现代 Java 中这些操作已被移除
- 状态查询应使用
Thread.getState(),而非依赖isAlive()判断细节状态
理解 start() 触发的状态变迁,关键在于区分 JVM 抽象层(NEW/RUNNABLE/TERMINATED)与操作系统执行层(实际调度与 CPU 占用),不复杂但容易忽略边界语义。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











