thread是线程本体,负责生命周期与资源管理;runnable是任务逻辑接口,只定义run()行为,需由thread或线程池执行,二者职责分离、不可互换。

继承 Thread 和实现 Runnable 都能启动线程,但根本不是“两种写法选一个”的关系——它们在职责、设计意图和运行机制上完全不同。
职责定位不同:一个是“线程本体”,一个是“任务逻辑”
Thread 是对操作系统线程的封装,它管理生命周期(new、runnable、blocked、terminated)、调度控制(start、interrupt、join)、系统资源(栈、优先级、线程组);
Runnable 只是一个接口,只声明一个无参无返回值的 run() 方法,纯粹描述“这个线程该做什么”。
它不创建线程,也不控制线程,甚至不能调用 start() ——必须交给 Thread 或线程池来执行。
继承结构限制不同:单继承 vs 多实现
Java 不支持多继承,所以:
- 若已继承某个业务类(比如
OrderService extends BaseService),就无法再extends Thread - 但可以同时
extends BaseService implements Runnable,毫无冲突 - Runnable 还可与其他接口共存(如
Serializable、Comparable),便于序列化或统一调度
资源复用与扩展能力不同:耦合 vs 解耦
继承 Thread 时,每个任务都得 new 一个新 Thread 实例:
- 每次
new Thread()都会分配独立栈内存、触发内核线程创建,开销大 - 无法共享任务状态(除非额外加 static 或外部对象),也不利于线程池复用
实现 Runnable 后:
- 同一个实例可被多个 Thread 构造器复用(如
new Thread(task)多次) - 天然适配
ExecutorService:executor.submit(task) - 可直接用 Lambda 表达式:
() -> { System.out.println("done"); },简洁且无类膨胀
本质上,Thread 负责“怎么跑”,Runnable 定义“跑什么”。把任务逻辑塞进 Thread 里,就像把菜谱写进炒锅——能用,但不该这么设计。










