start()是启动新线程的唯一合法方式,会创建os线程并使线程进入runnable状态;run()只是普通方法,直接调用不创建线程、不改变状态、无并发性,始终在当前线程同步执行。

本质区别在于:start() 是启动新线程的唯一合法方式,而 run() 只是定义任务逻辑的普通方法——调用它不会创建线程,也不会并发执行。
start() 触发线程生命周期的真正开始
调用 start() 后,JVM 会做几件关键的事:
- 向操作系统申请资源,创建一个独立的 OS 线程
- 为该线程分配专属栈空间和线程 ID
- 将线程状态从 NEW 改为 RUNNABLE(就绪),加入调度队列
- 由 JVM 底层在合适时机自动回调 run() 方法——你无法控制何时执行
此时主线程立即继续运行,子线程在后台异步执行,两者互不阻塞。
run() 就是个普通 Java 方法
它没有线程创建能力,也不改变线程状态。直接调用 t.run() 的效果等同于调用任何对象的普通方法:
- 代码仍在当前线程(比如 main)中同步执行
- 如果 run() 里有 Thread.sleep(5000),主线程就会卡住 5 秒
- t1.run(); t2.run(); 是严格串行的,毫无并发性
- 多次调用不会报错,但始终跑在同一个线程里
状态与调用规则完全不同
start() 和 run() 在线程状态管理上泾渭分明:
- start() 只能调用一次;重复调用抛 IllegalThreadStateException
- run() 可反复调用,没有任何限制
- 只有 start() 能让线程进入 RUNNABLE 状态;run() 调用前后线程状态不变
- 只有通过 start() 启动的线程,才能被 interrupt() 中断、被线程池管理、响应优先级调度
底层实现机制差异明显
技术细节上,二者根本不在一个层级:
- start() 是 synchronized 的 native 方法,内部调用 start0(),最终依赖操作系统 API 创建线程
- run() 是纯 Java 实现的普通实例方法,默认只是转发 target.run(),无任何并发语义
- Thread.currentThread().getName() 在 start() 启动的子线程中返回 t1/t2,在 run() 调用中永远显示 main
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











