start()不能重复调用,因threadStatus状态变更后校验失败抛IllegalThreadStateException;它通过native start0()桥接JVM与操作系统创建原生线程,再回调run(),而直接调用run()仅是同步方法执行。

调用 start() 不是直接执行代码,而是触发 JVM 向操作系统申请一个原生线程,并让它最终去跑你的 run() 方法。
start() 为什么不能重复调用
每个 Thread 对象内部有一个 threadStatus 字段,初始为 0。一旦成功调用 start(),start0() 执行后该状态就被设为非 0。再次调用时,start() 方法开头就会检查并抛出 IllegalThreadStateException 异常。
- 线程生命周期不可逆:Java 规定一个线程只能启动一次,这是语义约束,不是技术限制
-
threadStatus是 JVM 内部维护的状态标识,不对外暴露,也不建议手动修改 - 试图复用 Thread 实例时,应新建对象而非重用已启动的实例
start0() 是真正的“桥梁”
start0() 是一个 native 方法,由 JVM 用 C/C++ 实现,它把 Java 层的线程请求翻译成操作系统能理解的指令。
- 在 Linux 上,通常通过
pthread_create()创建 POSIX 线程 - 在 Windows 上,一般调用
CreateThread()或_beginthreadex() - 创建成功后,原生线程会绑定到对应的 Java
Thread对象,并准备执行其run() - JVM 会为该线程分配栈空间、设置上下文,并注册信号处理等底层资源
run() 不是线程入口,只是被调度执行的目标
直接调用 run() 就像调用任意普通方法——它仍在当前线程中同步执行,不会产生新线程。而 start() 的作用,是让 JVM 安排一个新线程,在那个线程里回调 run()。
立即学习“Java免费学习笔记(深入)”;
- 如果构造
Thread时传入了Runnable,则run()内部会委托给target.run() - 如果是继承
Thread并重写run(),就执行子类版本 - 这个回调发生在新线程上下文中,所以
Thread.currentThread()在其中返回的是新线程对象
操作系统与 JVM 的协作流程
整个过程不是 Java 单方面完成的,而是 JVM 充当“中间人”,协调 Java 逻辑和系统资源:
- JVM 先校验线程状态、加入线程组、预分配结构体(如
JavaThread) - 调用
os::start_thread()(位于os_linux.cpp或os_windows.cpp)真正发起系统调用 - 原生线程启动后,会进入 JVM 预设的入口函数(如
thread_entry),再跳转到 Java 层的run() - 线程终止时,JVM 清理资源并从线程组中移除该对象,但对象本身仍可被引用(只是状态变为 TERMINATED)


















