new → runnable 的唯一入口是 start();线程对象创建后处于NEW状态,仅调用start()才能进入RUNNABLE,该状态涵盖就绪和运行两种OS级状态,且不可逆。

new → runnable 的唯一入口是 start()
线程对象一用 new Thread() 创建出来,状态就是 NEW;它此时只是 JVM 堆里的一个普通对象,没分配任何线程资源,更不会执行 run()。想让它“活起来”,必须且只能调用 start() ——不是 run(),也不是其他方法。
常见错误是直接调用 thread.run():这只会当作普通方法同步执行,不启动新线程,状态永远卡在 NEW(因为没调 start()),也不会变成 RUNNABLE。
-
start()是 JVM 线程启动的“开关”,触发底层 OS 线程创建、栈分配、调度注册 - 调用
start()后,线程状态立刻变为RUNNABLE,但不保证马上执行run()方法体 - 同一线程上调用两次
start()会抛IllegalThreadStateException
RUNNABLE 不等于“正在 CPU 上跑”
Java 的 RUNNABLE 是一个抽象状态,涵盖操作系统层面的“就绪(Ready)”和“运行(Running)”两种情况。JVM 不区分它们,统一报 RUNNABLE。
这意味着:一个状态为 RUNNABLE 的线程,可能正被 CPU 执行,也可能在就绪队列里排队,甚至因 I/O 等待陷入内核态(比如读磁盘、网络阻塞),但 JVM 仍认为它是 RUNNABLE。
- 别靠
getState() == RUNNABLE判断“是否真在干活”,它只说明线程具备执行资格 - 真正阻塞(如锁竞争、无超时等待)才会进入
BLOCKED/WAITING/TIMED_WAITING - 监控工具(如 jstack)看到的
RUNNABLE线程,也可能卡在系统调用里,需结合 native stack 分析
从 NEW 到 TERMINATED 的路径不可逆
线程一旦进入 TERMINATED,就彻底结束,不能再 reset、restart 或复用。这是 Java 线程模型的硬约束。
有人误以为中断(interrupt())或调用 stop() 能“切换到 TERMINATED”,这是危险误解:stop() 已废弃多年,强制终止会破坏锁一致性;interrupt() 只是设个标志位,是否退出由线程自己决定。
-
TERMINATED只有两种合法出口:正常执行完run()方法,或抛出未捕获异常 - 线程池里的“空闲线程”仍是
RUNNABLE(等待新任务),不是TERMINATED - 别试图对已
TERMINATED的线程调start(),会直接抛异常
调试时怎么确认状态转换发生了
单纯打印 thread.getState() 容易误判,因为状态是瞬时快照。比如刚调完 start() 就查,可能还是 NEW(还没来得及切换);或者查到 RUNNABLE 就以为在执行,其实刚被调度器挂起。
更可靠的方式是结合日志埋点 + 主动同步观察:
- 在
run()方法第一行打日志,再查状态:如果日志已输出,那状态必然是RUNNABLE或之后的状态 - 用
Thread.sleep(10)给状态切换留出时间窗口,再查 - 多线程环境下,避免用主线程查子线程状态——加锁或用
CountDownLatch确保时序
最易被忽略的一点:RUNNABLE 是 JVM 层面的“可运行”视图,它不反映真实 CPU 占用或 OS 级阻塞。要定位性能瓶颈,不能只看 Java 状态,得配合 top -H、perf 或 jstack -l 看 native stack。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











