"implements Runnable" vs "extends Thread" in Java

“implements Runnable” vs “extends Thread” in Java

技术背景

在 Java 多线程编程中,实现多线程有两种常见方式:实现 Runnable 接口和继承 Thread 类。这两种方式都能实现多线程的功能,但在使用场景、设计理念和实际应用中存在一些差异。了解它们的区别,有助于开发者根据具体需求选择合适的方式进行多线程编程。

实现步骤

实现 Runnable 接口

  1. 创建一个类实现 Runnable 接口。
  2. 重写 run() 方法,在该方法中定义线程要执行的任务。
  3. 创建该类的实例。
  4. 将该实例作为参数传递给 Thread 类的构造函数,创建 Thread 对象。
  5. 调用 Thread 对象的 start() 方法启动线程。

继承 Thread

  1. 创建一个类继承 Thread 类。
  2. 重写 run() 方法,在该方法中定义线程要执行的任务。
  3. 创建该类的实例。
  4. 调用该实例的 start() 方法启动线程。

核心代码

实现 Runnable 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 实现 Runnable 接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Running task implemented by Runnable");
}
}

public class RunnableExample {
public static void main(String[] args) {
// 创建 MyRunnable 实例
MyRunnable myRunnable = new MyRunnable();
// 创建 Thread 对象并传入 MyRunnable 实例
Thread thread = new Thread(myRunnable);
// 启动线程
thread.start();
}
}

继承 Thread

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 继承 Thread 类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Running task implemented by extending Thread");
}
}

public class ThreadExample {
public static void main(String[] args) {
// 创建 MyThread 实例
MyThread myThread = new MyThread();
// 启动线程
myThread.start();
}
}

最佳实践

优先选择实现 Runnable 接口

  • 可扩展性:Java 不支持多重继承,实现 Runnable 接口的类还可以继承其他类,增加了代码的灵活性。
  • 代码复用:可以将同一个 Runnable 对象传递给多个 Thread 对象,多个线程可以共享同一个任务。
  • 分离任务和执行:将任务的定义和执行分离,符合单一职责原则,提高了代码的可维护性。

使用线程池

在 Java 5 及以上版本,建议使用 ExecutorService 线程池来管理线程,而不是直接创建 Thread 对象。这样可以更好地控制线程的数量和生命周期,提高性能和资源利用率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Running task in thread pool");
}
}

public class ThreadPoolExample {
public static void main(String[] args) {
// 创建线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 提交任务
executorService.execute(new MyRunnable());
// 关闭线程池
executorService.shutdown();
}
}

常见问题

为什么不能直接调用 run() 方法?

直接调用 run() 方法不会启动新线程,而是在当前线程中顺序执行 run() 方法中的代码。要启动新线程,必须调用 start() 方法。

继承 Thread 类有什么缺点?

  • 单继承限制:由于 Java 不支持多重继承,继承 Thread 类后就不能再继承其他类,限制了代码的可扩展性。
  • 资源浪费:每个线程都需要创建一个独立的 Thread 子类对象,可能会导致资源浪费。

实现 Runnable 接口和继承 Thread 类在资源消耗上有区别吗?

从本质上来说,两者在资源消耗上没有太大区别,因为最终都需要创建 Thread 对象来启动线程。但实现 Runnable 接口可以更好地复用任务,避免创建过多的 Thread 对象。


"implements Runnable" vs "extends Thread" in Java
https://119291.xyz/posts/implements-runnable-vs-extends-thread-in-java/
作者
ww
发布于
2025年5月15日
许可协议