Java 创建线程:继承 Thread 子类 vs 实现 Runnable 接口

一、两种方式代码示例

方式 1:继承 Thread 类创建线程

通过自定义类继承Thread,重写run()方法,调用start()启动线程。

// 继承Thread子类
class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("线程正在执行任务");
    }
}

public class TestThread{
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();
    }
}

方式 2:实现 Runnable 接口创建线程

自定义类实现Runnable接口,把任务传入 Thread 对象,再启动线程。

// 实现Runnable接口
class MyTask implements Runnable{
    @Override
    public void run() {
        System.out.println("线程正在执行任务");
    }
}

public class TestRunnable{
    public static void main(String[] args) {
        MyTask task = new MyTask();
        Thread t1 = new Thread(task);
        t1.start();
    }
}

二、核心区别对比

1. 继承关系不同(最大区别)

  • 继承 Thread 类:Java 是单继承,一旦继承了Thread,就不能再继承其他父类,会限制代码的扩展性。
  • 实现 Runnable 接口:只是实现接口,当前类还可以继承别的父类,更加灵活,规避了单继承的限制。

2. 任务资源共享能力不同

  • 继承 Thread 类:每创建一个Thread子类对象,都是独立的线程实例,无法直接共享同一个任务资源,必须借助静态变量才能实现共享。
  • 实现 Runnable 接口:多个Thread对象可以传入同一个 Runnable 任务实例,天然可以共享任务中的成员变量,非常适合多线程售票、计数这类资源共享场景。

资源共享示例(Runnable 方式):

class TicketTask implements Runnable{
    private int ticket = 10;
    @Override
    public void run() {
        while(ticket > 0){
            ticket--;
            System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余:"+ticket);
        }
    }
}

public class ShareResource{
    public static void main(String[] args) {
        TicketTask task = new TicketTask();
        // 3个线程共用同一个任务对象,共享ticket变量
        new Thread(task,"窗口1").start();
        new Thread(task,"窗口2").start();
        new Thread(task,"窗口3").start();
    }
}

3. 任务与线程解耦程度不同

  • 继承 Thread:线程对象和任务代码耦合在一起,线程和任务绑定,一个线程对应一套任务。
  • 实现 Runnable:把 ** 任务(Runnable)执行载体(Thread 线程)** 分离开,任务可以被任意多个线程复用,代码解耦更好。

4. 代码复用性

  • 继承 Thread:线程类只能作为线程运行,复用性弱。
  • 实现 Runnable:Runnable 只是普通任务类,既可以交给 Thread 执行,也可以交给线程池执行,通用性更强。

三、总结优缺点

表格

对比项 继承 Thread 子类 实现 Runnable 接口
继承限制 受 Java 单继承约束,不能再继承其他类 无继承限制,可同时继承父类 + 实现多个接口
资源共享 多个线程无法直接共享任务数据 多线程可以共享同一个 Runnable 任务资源
代码耦合 线程与任务强耦合 任务和线程解耦,职责分离
适用场景 简单独立的一次性线程任务 多线程资源共享、线程池、业务解耦场景

开发建议

日常项目开发中,优先使用实现 Runnable 接口的方式创建线程,规避单继承缺陷,同时更好地实现多线程数据共享;只有简单的独立线程任务,才偶尔使用继承 Thread 的写法。


四、拓展:底层原理

两种方式最终都是调用start()来启动线程,由 JVM 自动调用run()方法。

  • 继承 Thread:重写的是 Thread 自身的run()
  • 传入 Runnable:Thread 内部会执行传入 Runnable 对象的run()方法。

一句话总结:继承 Thread 是把线程和任务写在一起;实现 Runnable 是把任务抽离出来,让线程去执行这个任务。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐