前言在Java并发开发体系中构建线程主要存在两种经典实现途径一是编写子类继承 Thread 父类二是自定义类实现 Runnable 接口并交由 Thread 对象承载执行。很多初学者仅会照搬模板编写代码却不清楚二者底层设计、适用场景与拓展性的核心差距本文结合实操案例从语法、设计、业务场景多角度拆解二者区别。一、两种实现方式完整代码示例方案1继承Thread类生成线程该方案的设计逻辑为自定义类直接继承 java.lang.Thread 重写内部 run() 方法承载线程业务逻辑实例化自定义类后调用 start() 方法启动线程。// 自定义线程类继承Threadpublic class ExtendThread extends Thread {// 重写run线程运行时执行该方法Overridepublic void run() {for (int num 1; num 8; num) {System.out.println(继承Thread线程输出数字 num);}}public static void main(String[] args) {// 构建两个独立线程对象ExtendThread threadOne new ExtendThread();ExtendThread threadTwo new ExtendThread();// 启动线程threadOne.start();threadTwo.start();}}方案2实现Runnable接口构建线程该方案将业务任务与线程执行载体拆分自定义类实现 Runnable 接口并重写 run() 封装业务再把任务实例传入 Thread 构造方法借助Thread完成线程创建与调度。// 业务任务类仅实现Runnable接口public class ImplRunnable implements Runnable {Overridepublic void run() {for (int num 1; num 8; num) {System.out.println(实现Runnable线程输出数字 num);}}public static void main(String[] args) {// 仅创建一份任务实例ImplRunnable task new ImplRunnable();// 多个线程共用同一个任务对象Thread threadOne new Thread(task);Thread threadTwo new Thread(task);threadOne.start();threadTwo.start();}}二、五大核心差异点深度对比1. 类继承约束不同最核心区分点Java语言严格遵循单类继承机制一个类仅能拥有一个直接父类- 继承 Thread 方案自定义类已经占用唯一继承名额后续无法再继承其他业务父类拓展性被锁死​- 实现 Runnable 方案接口支持多实现类实现Runnable后依旧可以正常继承其他父类、实现多个业务接口不会限制类的层级拓展。2. 多线程资源共享能力天差地别线程开发高频场景为多个线程操作同一公共资源车票、库存、计数器等两种方案表现完全不同1. 继承Thread每次 new 自定义线程类都会生成全新独立对象每个对象拥有专属成员变量线程之间无法共用数据​2. 实现Runnable仅需实例化一份任务对象多个Thread传入同一个任务实例所有线程共享任务内部成员变量天然适配资源争抢场景。车票售卖实操案例Runnable共享资源// 车票售卖任务多窗口共享票数public class SaleTicketTask implements Runnable {// 所有线程共享的车票库存private int ticketCount 12;Overridepublic void run() {while (ticketCount 0) {System.out.println(Thread.currentThread().getName() 售出剩余第 ticketCount 张车票);ticketCount--;}}public static void main(String[] args) {SaleTicketTask ticketTask new SaleTicketTask();// 三个窗口共用车票任务new Thread(ticketTask, 一号售票窗口).start();new Thread(ticketTask, 二号售票窗口).start();new Thread(ticketTask, 三号售票窗口).start();}}若采用继承Thread方式编写售票逻辑每新建一个窗口对象都会生成独立车票库存无法实现多窗口统一售票。3. 代码分层与耦合程度不一样- Thread继承模式线程载体、业务逻辑全部耦合在同一个类中线程运行机制和业务代码高度绑定后期如需更换线程执行方式需要大规模修改业务代码​- Runnable实现模式遵循职责单一设计思想Runnable只负责编写业务逻辑Thread仅负责操作系统线程的创建、调度、生命周期管理二者完全解耦便于单独维护、替换。4. 底层执行逻辑细微区分两种方式最终都会调用底层native方法 start0() 向操作系统申请创建线程执行入口均为 run() 方法内部调用逻辑存在区别1. 继承Thread线程本身就是任务载体执行时直接调用自身重写的 run() ​2. 实现RunnableThread内部持有Runnable成员变量执行时判断任务不为空调用 runnable.run() 本质是线程代理执行外部任务。5. 代码书写简洁度- 继承Thread代码行数更少无需额外创建Thread对象对新手入门友好​- 实现Runnable需要多一层任务类封装基础代码量略多但Java 8 Lambda表达式可大幅简化编写无需单独定义实现类public class LambdaThreadDemo {public static void main(String[] args) {// Lambda简化Runnable写法省去独立类定义new Thread(() - {System.out.println(Lambda简化实现Runnable线程);}).start();}}三、两种实现方式优缺点汇总继承Thread子类优势代码直观简短入门学习成本低直接实例化即可启动线程。短板受单继承限制拓展性差、多线程无法共享资源、业务与线程逻辑高度耦合企业项目极少使用。实现Runnable接口优势突破单继承限制、多线程共享公共资源、代码分层解耦、适配Lambda简化写法是工业级项目标准方案。短板基础写法需要额外搭配Thread对象初学阶段代码结构稍复杂。四、实际开发选用规范1. 业务开发、并发业务库存、订单、多窗口任务强制选用Runnable实现方案​2. 仅做简单Demo演示、无拓展需求的极简测试代码可临时使用继承Thread方式​3. Java 8及以上版本优先使用Lambda表达式简化Runnable代码减少冗余类文件。五、补充拓展除本文两种基础方案外Java还提供 CallableFutureTask 实现带返回值的线程适用于需要获取线程执行结果的场景底层同样基于Runnable接口拓展而来本质依旧是任务与线程分离的设计思路侧面印证Runnable模式的设计优势。