在 Java 中,线程是实现并发编程的核心。主要有以下三种:
- 继承
Thread
类 - 实现
Runnable
接口 - 实现
Callable
接口并结合Future
使用
1. 继承 Thread
类
继承 Thread
类是创建线程的最简单方式之一。通过扩展 Thread
类并重写其 run
方法,可以定义线程的具体执行任务。使用这种方式时,每个线程对象都有自己独立的线程执行体。
示例
class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");}public static void main(String[] args) {MyThread thread1 = new MyThread();thread1.start(); // 启动线程}
}
总结
- 优点: 代码结构简单,直接通过
Thread
类的子类实现线程功能。 - 缺点: Java 不支持多继承,继承
Thread
类会限制类的扩展性;线程任务和线程控制耦合在一起,不利于灵活性和重用性。
2. 实现 Runnable
接口
实现 Runnable
接口是另一种创建线程的方式。通过实现 Runnable
接口并重写 run
方法,可以将线程任务与线程控制分离。创建线程时,只需将 Runnable
实例传递给 Thread
构造器即可。
示例
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");}public static void main(String[] args) {Thread thread2 = new Thread(new MyRunnable());thread2.start(); // 启动线程}
}
总结
- 优点: 避免了 Java 的单继承限制,可以与其他类一起实现;线程任务与线程控制分离,提高了代码的灵活性和可复用性。
- 缺点: 相比于继承
Thread
类,需要额外的Thread
实例来启动线程。
3. 实现 Callable
接口并结合 Future
使用
Callable
接口是 Java 5 引入的,提供了比 Runnable
更强大的功能。Callable
可以在任务执行完成后返回结果,并且支持抛出异常。结合 Future
接口使用,可以通过 Future
获取任务的执行结果或状态。
示例
import java.util.concurrent.*;class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {return "线程 " + Thread.currentThread().getName() + " 执行完成";}public static void main(String[] args) throws Exception {ExecutorService executor = Executors.newSingleThreadExecutor();Future<String> future = executor.submit(new MyCallable());System.out.println(future.get()); // 获取并打印执行结果executor.shutdown();}
}
总结
- 优点:
Callable
可以返回执行结果,支持抛出异常;结合Future
,可以获取任务的执行状态和结果。 - 缺点: 需要结合线程池和
Future
使用。
对比
特性 | 继承 Thread 类 | 实现 Runnable 接口 | 实现 Callable 接口 |
---|---|---|---|
实现难度 | 简单 | 较简单 | 稍复杂 |
返回结果 | 无 | 无 | 有 |
异常处理 | 无法处理 | 无法处理 | 可以抛出异常 |
复用性 | 差 | 好 | 好 |
多线程启动 | start() | start() | 结合线程池启动 |
总之
- 继承
Thread
类 适合简单的线程任务,代码简洁但不灵活。 - 实现
Runnable
接口 是一种更灵活的方式,适用于大多数场景。 - 实现
Callable
接口 适合需要返回结果或处理异常的复杂任务。