一、实现方式原理

1. 继承 Thread 子类方式

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

class MyThread extends Thread{
    @Override
    public void run() {
        // 线程执行逻辑
    }
}
// 使用
MyThread t = new MyThread();
t.start();

2. 实现 Runnable 接口方式

自定义类实现Runnable接口,实现run()方法,将该实现类对象传入Thread构造器,再调用start()

class MyTask implements Runnable{
    @Override
    public void run() {
        // 线程执行逻辑
    }
}
// 使用
MyTask task = new MyTask();
Thread t = new Thread(task);
t.start();

二、核心区别对比

1. 类继承限制(最关键)

  • 继承 Thread:Java 是单继承,一旦继承Thread,该类无法再继承其他父类,扩展性差。
  • 实现 Runnable:接口可多实现,实现Runnable后还能继承其他类、实现多个接口,无继承限制。

2. 资源共享能力

  • 继承 Thread:每个线程对象都是独立的Thread子类实例,无法天然共享成员变量,要共享数据需要静态变量,操作麻烦。
  • 实现 Runnable:多个Thread对象可以传入同一个 Runnable 任务对象,天然共享任务里的成员变量,适合多线程卖票、计数器等共享资源场景。 示例(多线程共享数据):
Runnable ticketTask = new TicketTask();
// 三个线程共用同一个任务,共享票数
new Thread(ticketTask).start();
new Thread(ticketTask).start();
new Thread(ticketTask).start();

3. 职责分离思想

  • 继承 Thread:把线程调度逻辑(Thread)业务执行逻辑(run) 耦合在同一个类中,不符合单一职责。
  • 实现 Runnable:任务逻辑和线程类解耦,Runnable只负责业务,Thread只负责线程调度,代码更清晰,便于复用任务。

4. 代码复用性

  • Runnable任务可以脱离线程独立存在,能被线程池、定时器等其他执行工具复用;
  • Thread子类绑定了线程本身,只能作为线程使用,复用场景受限。

5. 底层本质

两种方式最终执行逻辑都依赖Threadstart()start()会调用底层操作系统创建线程,再自动执行run()

  • 继承 Thread:重写自身的run()
  • 实现 Runnable:Thread 内部持有target(Runnable),执行target.run()

三、开发推荐

日常开发优先使用实现 Runnable 接口的方式,仅在无需共享资源、不需要继承其他类的简单场景下才考虑继承 Thread。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐