Java 多线程入门:继承 Thread vs 实现 Runnable
一、引言在 Java 多线程编程的入门阶段我们最常遇到的第一个问题就是如何创建一个线程通常老师会教我们两种方法继承Thread类并重写run()方法。实现Runnable接口创建任务对象再交给Thread执行。这两种方式都能实现多线程但它们之间到底有什么区别为什么在实际开发中绝大多数场景都推荐使用Runnable这篇博客就带你彻底搞懂这两种方式的底层差异、优缺点和适用场景。二、两种方式的代码示例1. 继承Thread类// 1. 定义Thread的子类 public class MyThread extends Thread { // 重写run()方法线程执行的逻辑写在这里 Override public void run() { System.out.println(线程 Thread.currentThread().getName() 正在执行任务); } public static void main(String[] args) { // 2. 创建线程对象 MyThread t1 new MyThread(); MyThread t2 new MyThread(); // 3. 启动线程 t1.start(); t2.start(); } }2. 实现Runnable接口// 1. 定义Runnable接口的实现类 public class MyRunnable implements Runnable { Override public void run() { System.out.println(线程 Thread.currentThread().getName() 正在执行任务); } public static void main(String[] args) { // 2. 创建任务对象 MyRunnable task new MyRunnable(); // 3. 将同一个任务对象交给多个线程执行 Thread t1 new Thread(task, 线程1); Thread t2 new Thread(task, 线程2); // 4. 启动线程 t1.start(); t2.start(); } }三、核心区别深度解析1. 类继承限制单继承 vs 接口实现继承Thread类Java 语言是单继承的如果你的类已经继承了其他父类比如class Task extends BaseService那么它就无法再继承Thread类了这会直接限制你的设计。实现Runnable接口接口是支持多实现的你的类可以一边继承其他父类一边实现Runnable接口代码的扩展性和灵活性更高。2. 资源共享能力耦合 vs 解耦继承Thread类每个Thread子类的实例都是一个独立的线程对象任务代码和线程本身是紧耦合的。如果多个线程需要执行同一个任务、共享同一份数据实现起来会非常麻烦通常需要借助静态变量来实现还可能引发线程安全问题。实现Runnable接口任务逻辑Runnable和线程执行器Thread是分离的。同一个Runnable对象可以被多个Thread对象共享天然支持多线程共享数据非常适合处理多线程卖票、生产者 - 消费者等场景。3. 职责定位线程本体 vs 任务逻辑Thread类它代表的是线程本身封装了线程的状态、优先级、生命周期管理等底层操作。继承它意味着你既要定义线程的执行逻辑又要继承线程的控制能力。Runnable接口它只代表一个可执行的任务里面只有一个run()方法不关心谁来执行它、怎么管理它。这种设计更符合 “单一职责原则”任务逻辑和线程控制分离代码更清晰。4. 实际应用场景原生线程 vs 线程池继承Thread类这种方式创建的线程对象无法被重复利用每次都要创建新的Thread实例开销较大也不支持线程池复用。实现Runnable接口Runnable任务可以被线程池直接管理和复用是 Java 并发包java.util.concurrent中所有线程池的基础接口也是企业级开发中的标准用法。四、优缺点对比表表格对比维度继承Thread类实现Runnable接口继承限制受 Java 单继承限制无法再继承其他类无限制可同时继承其他类、实现多个接口资源共享难以共享数据需依赖静态变量天然支持多线程共享同一任务对象耦合度高任务与线程绑定在一起低任务与线程分离可复用性强扩展性差功能扩展受限于 Thread 类好可通过接口实现、线程池灵活扩展推荐程度仅适用于简单、一次性场景企业级开发首选几乎所有场景都推荐五、为什么推荐使用Runnable从上面的对比可以看出Runnable接口的优势几乎是全方位的核心原因有三点符合 Java 设计原则接口解耦任务逻辑和线程控制分离代码更易维护。支持资源共享同一个任务可以被多个线程执行天然支持多线程协作。适配线程池现代 Java 并发编程中几乎所有的线程都是由线程池管理的而线程池只接受Runnable或Callable任务。六、总结继承Thread类的方式虽然简单但受限于 Java 单继承耦合度高扩展性差只能作为入门了解。实现Runnable接口的方式更符合面向对象设计思想解耦、可扩展、支持资源共享是实际开发中的标准选择。理解这两种方式的区别不仅能帮你写出更规范的多线程代码更能让你理解 Java 并发编程的核心设计思想 ——分离关注点提高可复用性。