java中启动线程必须调用start()而非run(),因为start()由jvm支持,负责检查状态、注册线程并调用native方法使线程进入runnable态,而run()只是普通同步方法,直接调用不会创建新线程。

Java中启动线程必须调用 start(),绝不能直接调用 run()。这是多线程编程最基础也最容易出错的关键点——调用 run() 只是普通方法调用,不产生新线程;而 start() 才真正触发 JVM 创建线程并调度执行。
start() 是线程启动的唯一合法入口
start() 方法由 JVM 提供底层支持,它完成三件关键事:
- 检查线程状态:若线程已启动(非 NEW 状态),立即抛出 IllegalThreadStateException
- 向 JVM 注册线程:分配栈空间、设置线程 ID、加入线程组
- 调用 native 的
start0(),将线程置为 RUNNABLE 状态,交由操作系统线程调度器管理
此时 run() 方法尚未执行——它要等线程被 CPU 调度后才在新线程中运行。所以 start() 和 run() 的执行是分离的、异步的。
run() 只是一个普通方法,和线程无关
run() 在 Thread 类中是 public void 方法,默认为空实现。它的本质是:
- 可被任意线程任意次数调用(无状态限制)
- 直接调用时,代码就在当前线程中同步执行,不会并发
- 只有当 start() 启动后,JVM 才会在新线程里自动调用它
例如:new Thread(() -> System.out.println("hello")).run(); 输出的线程名一定是 "main",说明它没离开主线程。
常见误用与后果对比
以下两种写法行为完全不同:
-
t.run();→ 串行执行,t 仍是 NEW 状态,无并发 -
t.start();→ 异步启动,t 进入 RUNNABLE,开启并发执行窗口
重复调用 start() 必抛异常;重复调用 run() 则完全合法但毫无意义——它只是反复在当前线程跑同一段逻辑。
正确使用模式建议
实际编码中应严格遵循:
- 定义任务:继承 Thread 或传入 Runnable,重写/实现 run() 方法
- 启动执行:只调用一次 start(),且确保在 NEW 状态下调用
- 避免混淆:绝不把 run() 当作“手动启动”方式;调试时可用 run() 快速验证逻辑,但上线必须用 start()
- 状态判断:用
getState()查看是否已进入 RUNNABLE,而不是靠 try-catch start() 来判断
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











