在 Java 多线程编程中,创建线程最常见的两种方式就是继承 Thread 类实现 Runnable 接口,今天我们就来把这两种方式掰扯清楚,帮你彻底搞懂它们的区别和适用场景。

一、两种方式的基础实现

先看最直观的代码示例,感受一下两种写法的区别。

1. 继承 Thread 类

// 自定义线程类,继承Thread
public class MyThread extends Thread {
    // 重写run()方法,定义线程要执行的任务
    @Override
    public void run() {
        System.out.println("线程运行中:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // 创建线程对象并启动
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        thread1.start(); // 启动第一个线程
        thread2.start(); // 启动第二个线程
    }
}

2. 实现 Runnable 接口

// 实现Runnable接口,定义任务类
public class MyRunnable implements Runnable {
    // 实现run()方法,定义线程要执行的任务
    @Override
    public void run() {
        System.out.println("线程运行中:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // 创建任务对象
        MyRunnable runnable = new MyRunnable();
        // 同一个任务对象,创建多个线程
        Thread thread1 = new Thread(runnable, "线程1");
        Thread thread2 = new Thread(runnable, "线程2");
        thread1.start();
        thread2.start();
    }
}

二、核心区别对比

我们从几个关键维度来拆解两者的差异

对比维度 继承 Thread 类 实现 Runnable 接口
继承限制 Java 不支持多继承,继承 Thread 类后无法再继承其他类 接口支持多实现,实现 Runnable 后仍可继承其他类
任务共享 每个线程对象是独立的,无法共享同一个任务实例 多个 Thread 对象可以共用同一个 Runnable 任务,天然支持资源共享
耦合度 线程对象和任务逻辑耦合在一起 线程对象和任务逻辑分离,解耦更彻底
扩展性 扩展性较差,只能通过重写 run () 方法扩展 扩展性更好,后续可以很方便地配合线程池等高级 API 使用

三、关键差异深度解析

1. 单继承限制的影响

Java 是单继承语言,如果你的类继承了Thread类,就不能再继承其他父类了,这会严重限制你的类的扩展能力。

举个例子:如果你的业务类本身需要继承一个BaseService父类,就无法再继承Thread,这种情况下只能选择实现Runnable接口。

2. 资源共享的能力差异

实现Runnable接口最大的优势就是可以让多个线程共享同一个任务实例。比如多个线程处理同一个计数器、同一个任务队列,用Runnable就非常方便,而继承Thread类的方式每个线程都是独立的对象,很难实现共享。

3. 代码解耦的设计思想

继承Thread类的方式,是把 “线程对象” 和 “任务逻辑” 写在了同一个类里,耦合度很高;而实现Runnable接口的方式,是把 “任务逻辑” 封装在 Runnable 中,再交给 Thread 去执行,完全遵循了 “线程是执行载体,任务是业务逻辑” 的设计原则,解耦更清晰,也更符合面向对象的设计思想。

四、什么时候该用哪种方式?

优先推荐:实现 Runnable 接口

绝大多数场景下,都推荐你用实现Runnable接口的方式:

你的类需要继承其他父类时

需要多个线程共享同一个任务 / 资源时

后续需要使用线程池、Callable 等高级多线程 API 时

追求代码解耦和扩展性时

可以使用:继承 Thread 类

只有在这些简单场景下,可以考虑继承 Thread 类:

你的类不需要继承其他类,也不需要共享任务

任务逻辑非常简单,只是快速创建一个独立的线程执行任务

教学演示或小型 Demo 场景,代码更直观

五、补充:start () 和 run () 的小误区

不管哪种方式,启动线程都必须调用start()方法,而不是直接调用run()方法!

start():会启动一个新线程,让线程进入就绪状态,等待 CPU 调度后自动执行run()方法

run():只是一个普通的方法调用,直接调用的话不会启动新线程,只会在当前线程中同步执行代码

六、总结

场景 推荐方式
多线程共享任务 / 资源 实现 Runnable
类需要继承其他父类 实现 Runnable
追求解耦和扩展性 实现 Runnable
快速创建简单线程 Demo 继承 Thread

一句话总结:实现 Runnable 接口是 Java 多线程编程的主流方式,继承 Thread 类更多是入门阶段的写法,实际开发中基本都会用 Runnable。

更多推荐