Java中创建线程应优先使用Runnable接口而非继承Thread类,因其规避单继承限制、支持天然资源共享、实现任务与线程解耦、符合职责分离原则。

Java 中创建线程的两种主流方式——继承 Thread 类和实现 Runnable 接口——表面看只是写法不同,实际在设计合理性、工程可维护性和并发适用性上差异显著。项目中几乎都倾向用 Runnable,但理解为什么,比记住结论更重要。
类继承限制决定扩展天花板
Java 是单继承语言,一旦类继承了 Thread,就再也不能继承其他父类。比如你有个业务模型类 OrderService 需要复用已有的 BaseService 功能,若它又想当线程,就只能放弃继承 BaseService,或改用组合,徒增复杂度。
而实现 Runnable 接口完全不受此约束:一个类可以同时继承 BaseService、实现 Runnable,还能再实现 Serializable 或 Comparable 等多个接口,结构更自然、演进更自由。
资源共享能力直接影响并发逻辑正确性
多线程处理同一份数据(如卖票、库存扣减)时,能否天然共享变量,是判断方案是否适合生产的关键。
立即学习“Java免费学习笔记(深入)”;
- 继承 Thread:每个线程对象都是独立实例,
private int ticket = 10;在每个子类对象里各存一份,结果是“窗口1卖10张,窗口2也卖10张”,明显错误;强行共享需改成static,但又引入静态污染、测试难、无法实例隔离等问题。 - 实现 Runnable:同一个
MyTask task = new MyTask();实例传给多个 Thread,ticket字段天然被所有线程共用,逻辑简洁且符合直觉。
任务与线程解耦提升复用与调度能力
继承 Thread 把“做什么”和“谁来做”绑死在一个类里,导致任务无法脱离线程载体复用。
- Runnable 任务对象可被反复使用:既能交给新 Thread 启动,也能提交到线程池(
executor.submit(task)),还能用于定时任务(Timer.schedule()),甚至作为 Lambda 表达式基础。 - Thread 子类则只能靠
new启动,无法适配现代并发工具链,后期替换成本高。
代码组织更贴近真实职责划分
Thread 类本质是线程的“执行引擎”,负责生命周期管理(start、join、interrupt);而业务逻辑属于“任务”,应由独立单元承载。
实现 Runnable 让分工清晰:任务类只关心“我要干什么”,线程类只负责“我怎么跑”。这种分离让单元测试更简单(直接调用 task.run() 即可验证逻辑),也让多人协作边界更明确。


















