调用start()才能真正启动新线程,run()仅是普通方法调用;应优先使用runnable接口封装任务并传入thread构造器;同一thread实例只能start()一次;需确保先start()再执行耗时操作,必要时用join()等待。

直接调用 run() 方法不会启动新线程,只是在当前线程(比如主线程)里同步执行方法体,本质上仍是单线程行为。要真正实现多线程,必须调用 start() 方法。
明确区分 start() 和 run() 的作用
start() 是线程启动的唯一合法入口:它通知 JVM 为该线程分配资源、进入就绪状态,并由调度器安排执行;run() 只是普通实例方法,谁调用就在谁的线程里跑,不触发任何并发机制。
- 错误写法:
myThread.run()→ 主线程串行执行,无并发 - 正确写法:
myThread.start()→ JVM 创建并调度新线程
创建线程时优先使用 Runnable 接口
把任务逻辑封装在 Runnable 实现类中,再交由 Thread 对象启动,能更清晰地体现“任务”与“执行者”的分离,也避免误调 run()。
- 定义任务:
Runnable task = () -> { System.out.println("子线程运行"); }; - 包装并启动:
new Thread(task).start(); - 这样即使不小心写了
task.run(),编译也能通过,但逻辑上更容易意识到这是在当前线程执行
检查线程是否已启动,防止重复调用 start()
同一个 Thread 实例只能调用一次 start(),多次调用会抛 IllegalThreadStateException。可在启动前加状态判断:
if (!thread.isAlive()) thread.start();- 或用标志位控制,避免因逻辑分支导致意外调用
run()
避免在主线程中阻塞等待子线程逻辑
不要把耗时操作写在 run() 外部、start() 之前,否则主线程先执行完全部代码,子线程还没来得及跑——看起来像没并发。
- 错误顺序:
doHeavyWork(); thread.start();→ 主线程先干完活了 - 正确顺序:
thread.start(); doHeavyWork();→ 并发推进 - 如需等待子线程结束,用
join(),而不是靠执行顺序“猜”并发效果
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











