直接继承Thread类并重写run()是最基础线程创建方式,但因单继承限制和灵活性差,现代开发推荐实现Runnable接口;调用run()无并发效果,必须调用start()才真正启动新线程。

直接继承 Thread 类并重写 run() 方法是 Java 中最基础的线程创建方式,但它在现代开发中已不推荐——除非你明确需要复用线程实例或控制线程生命周期细节。
为什么 run() 里写逻辑却没效果?
常见错误是调用了 run() 而非 start():前者只是普通方法调用,仍在当前线程执行;后者才真正触发 JVM 创建新线程并回调 run()。
- ✅ 正确:
new MyThread().start(); - ❌ 错误:
new MyThread().run();(无并发,无新线程) - ⚠️ 注意:
start()只能调用一次,重复调用抛IllegalThreadStateException
Thread 子类 vs Runnable 实现的区别
继承 Thread 类会强制占用唯一的父类位置,无法再继承其他类;而实现 Runnable 接口更灵活,也更符合“组合优于继承”的设计原则。
- 子类化
Thread:适合极简场景,比如临时调试、教学示例 - 实现
Runnable:生产环境首选,可被Thread、ExecutorService等多种载体消费 - 性能差异:无本质区别;但
Thread对象本身较重(含线程资源),不应频繁 new
如何安全地向 run() 传参?
Thread 构造器不接受业务参数,必须通过成员变量传递,且要注意可见性问题。
- 用
final或不可变对象(如String、Integer)最安全 - 若需传可变对象(如
List),应确保只读访问,或加锁/使用线程安全容器 - 避免在
run()中直接引用外部非线程安全对象的字段 - 示例:
class CounterThread extends Thread { private final int count; CounterThread(int count) { this.count = count; } public void run() { for (int i = 0; i < count; i++) System.out.println(i); } }
真正难的不是写对 run(),而是处理共享状态、中断响应、异常捕获和资源释放——这些在继承 Thread 后容易被忽略,因为 run() 抛出的异常会静默终止线程,不会传播到父线程。

















