java多线程最不推荐继承thread类,因其违反单一职责、受单继承限制、线程与业务强耦合、无法复用、不可多次启动且不利于测试;应优先使用runnable接口实现任务与线程分离。

直接继承 Thread 类并重写 run() 方法,确实能启动线程,但这是最不推荐的多线程实现方式——它破坏了类的单一职责,且无法复用已有类结构。
为什么 Thread 子类方式在实际项目中几乎不用
Java 是单继承语言,一旦你让业务类(比如 OrderProcessor)继承 Thread,它就再也不能继承其他父类;同时,Thread 本身已经封装了大量与线程调度、状态管理相关的逻辑,把业务代码塞进子类里,会让职责严重混杂。
- 无法对同一业务对象多次启动线程(
start()只能调一次,重复调用抛IllegalThreadStateException) - 线程对象和业务逻辑强耦合,不利于单元测试(比如想 mock 线程行为?基本做不到)
- 所有子类实例都携带完整
Thread开销(哪怕只是临时跑个简单任务)
run() 和 start() 的区别必须分清
重写 run() 只是定义了线程要执行的逻辑;真正触发并发执行的是 start()。如果误调 run(),它就在当前线程同步执行,根本没开新线程。
class MyThread extends Thread {
public void run() {
System.out.println("线程名:" + Thread.currentThread().getName());
}
}
// ✅ 正确:新开线程执行
new MyThread().start();
// ❌ 错误:只是普通方法调用,在主线程里跑
new MyThread().run();
替代方案:优先用 Runnable + Thread 构造器
把任务逻辑和线程载体分离——业务类实现 Runnable,再丢给 Thread 实例去执行。这样既保持类的可扩展性,又符合面向接口编程原则。
- 一个
Runnable实例可被多个Thread复用(虽然通常不这么干) - 后续迁移到
ExecutorService几乎零成本:executor.submit(myRunnable) - Lambda 支持友好:
new Thread(() -> System.out.println("ok")).start();
真正需要关注的不是“怎么继承 Thread”,而是“如何让并发逻辑可维护、可测试、可演进”。硬套继承模式,往往是在为后续加锁、中断、超时等真实需求埋坑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











