调用start()后线程立即变为runnable状态而非直接执行run();runnable包含就绪和运行两种情形,实际执行需调度器分配cpu;遇到同步、i/o或等待会转入blocked/waiting/timed_waiting;run()结束后进入terminated状态且不可重启。

调用 start() 方法后,线程并不会立即执行 run() 方法,而是经历一系列受 JVM 管理的状态转换。这个过程不是原子操作,涉及线程调度器介入、操作系统资源分配和 JVM 内部状态同步。
NEW → RUNNABLE:start() 触发的瞬间变化
线程对象刚被创建时处于 NEW 状态。一旦调用 start(),JVM 会为其分配必要资源(如程序计数器、Java 虚拟机栈、本地方法栈),并将其状态设为 RUNNABLE(注意:不是“RUNNING”)。此时线程已进入就绪队列,等待 CPU 时间片,但尚未开始执行 run() 中的代码。
-
start()只能调用一次,重复调用抛出IllegalThreadStateException - 状态切换由 JVM 底层实现,Java 层无法直接干预或观察中间过渡
-
isAlive()在start()后立刻返回true,即使run()还没开始执行
RUNNABLE → RUNNING:调度器分配 CPU 的实际执行
RUNNABLE 包含“就绪”和“正在运行”两种含义。当操作系统线程调度器选中该线程并分配 CPU 时间片时,它才真正进入执行阶段(即通常理解的“running”)。此时 JVM 开始执行 run() 方法体中的字节码。
- 是否立刻执行取决于系统负载、线程优先级和调度策略,可能有微小延迟
- 即使只有一个 CPU 核心,多个
RUNNABLE线程也会通过时间片轮转交替执行 - 可通过
Thread.yield()主动让出 CPU,回到RUNNABLE状态等待下一次调度
RUNNABLE 与 BLOCKED/WAITING/TIMED_WAITING 的边界
线程在 run() 执行过程中遇到同步块、I/O 或显式等待(如 wait()、sleep()、join())时,会离开 RUNNABLE 状态:
- 进入
BLOCKED:等待获取 synchronized 锁(锁被其他线程持有) - 进入
WAITING:调用Object.wait()、Thread.join()(无超时)等无限期等待 - 进入
TIMED_WAITING:调用Thread.sleep(100)、wait(500)、join(200)等带超时的等待 - 这些状态退出后,线程重新回到
RUNNABLE,而非直接恢复执行 —— 仍需等待调度器再次分配 CPU
RUNNABLE → TERMINATED:run() 正常结束或异常终止
当 run() 方法执行完毕(正常 return)或因未捕获异常而退出时,线程生命周期终结,状态变为 TERMINATED。此时 JVM 会回收其栈帧等资源,但线程对象本身仍可访问(如调用 getState() 返回 TERMINATED)。
-
TERMINATED线程不可重启,再次调用start()会抛异常 - 不能通过
interrupt()唤醒已终止线程,也不会响应中断状态 - 建议使用
isAlive()判断线程是否仍在运行,而非依赖getState()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











