必须用start()启动线程,它才是操作系统级线程创建指令;run()只是普通方法调用,不产生新线程,仅在当前线程同步执行。

启动线程必须用 start(),不能用 run()——这不是写法偏好,而是是否真正产生新线程的分水岭。
start() 是线程启动的“操作系统级指令”
它不是普通 Java 方法,而是 synchronized native 方法,底层调用 start0(),最终依赖操作系统 API 创建独立线程:
- 向 OS 申请资源,分配专属栈空间和线程 ID
- 将线程状态从 NEW 改为 RUNNABLE
- 把线程加入 JVM 调度队列,由系统择机执行其
run() - 主线程立刻继续运行,不等待子线程;两者真正并发
run() 只是定义任务的普通方法
它没有线程创建能力,也不触发任何状态变更,本质等同于你写的 doWork():
- 直接调用
t.run(),代码仍在当前线程(如main)中同步执行 - 若
run()里有Thread.sleep(5000),主线程就会卡住 5 秒 -
t1.run(); t2.run();是严格串行,毫无并发性 - 可重复调用,无状态限制,也不会抛异常
状态与行为完全不可互换
二者在线程生命周期管理上毫不兼容:
-
start()只能调用一次;重复调用立即抛IllegalThreadStateException - 只有通过
start()启动的线程,才能被interrupt()中断、被线程池管理、响应优先级调度 -
Thread.currentThread().getName()在start()启动的子线程中返回t1/t2,而run()调用中永远显示main
误用 run() 的真实代价
线上故障中,“假并发”占比超三成:看似开了多个线程,实则所有逻辑挤在主线程串行跑。结果是:
- 耗时操作阻塞整个应用响应
- 并发设计形同虚设,压测吞吐量不升反降
- 调试时发现所有日志都打在同一个线程名下,却误以为是多线程问题
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











