在 Java 中,创建线程主要有以下四种方式,每种方式都有其特点和适用场景:
1. 继承 Thread 类
这是最基础的线程创建方式,通过继承Thread类并重写其run()方法来定义线程执行体。
// 定义线程类
class MyThread extends Thread {
@Override
public void run() {
// 线程执行的任务
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " 执行: " + i);
try {
Thread.sleep(100); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 使用线程
public class ThreadExample {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.setName("线程1");
thread2.setName("线程2");
// 启动线程,会自动调用run()方法
thread1.start();
thread2.start();
}
}
特点:
- 简单直接,通过继承实现
- 缺点是 Java 单继承限制,继承 Thread 后不能再继承其他类
- 适合简单的线程任务
2. 实现 Runnable 接口
通过实现Runnable接口的run()方法来定义线程任务,然后将其传递给 Thread 对象。
// 实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的任务
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " 执行: " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 使用线程
public class RunnableExample {
public static void main(String[] args) {
// 创建任务对象
MyRunnable task = new MyRunnable();
// 创建线程并关联任务
Thread thread1 = new Thread(task, "线程1");
Thread thread2 = new Thread(task, "线程2");
// 启动线程
thread1.start();
thread2.start();
}
}
特点:
- 避免了单继承限制,一个类可以同时实现多个接口
- 适合多个线程共享同一个任务资源的场景
- 代码结构更清晰,任务与线程控制分离
3. 实现 Callable 接口
Callable接口是 Java 5 引入的,与Runnable类似但可以返回结果,并且可以抛出异常。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
// 实现Callable接口,泛型指定返回值类型
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 5; i++) {
sum += i;
System.out.println(Thread.currentThread().getName() + " 计算: " + i);
Thread.sleep(100);
}
return sum; // 返回计算结果
}
}
// 使用Callable
public class CallableExample {
public static void main(String[] args) {
// 创建Callable任务
MyCallable callable = new MyCallable();
// 将Callable包装成FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 创建线程并启动
Thread thread = new Thread(futureTask, "计算线程");
thread.start();
try {
// 获取线程执行结果,会阻塞直到结果返回
int result = futureTask.get();
System.out.println("计算结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
特点:
- 可以返回执行结果
- 可以抛出受检查异常
- 需要通过
FutureTask包装后才能传递给 Thread - 适合需要获取线程执行结果的场景
4. 使用线程池
Java 5 引入的Executor框架提供了线程池功能,可以高效管理和复用线程。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// 线程任务
class Task implements Runnable {
private int taskId;
public Task(int id) {
this.taskId = id;
}
@Override
public void run() {
System.out.println("任务 " + taskId + " 由 " + Thread.currentThread().getName() + " 执行");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 使用线程池
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建固定大小的线程池,包含3个线程
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交5个任务给线程池
for (int i = 1; i <= 5; i++) {
executor.submit(new Task(i));
}
// 关闭线程池
executor.shutdown();
}
}
特点:
- 避免频繁创建和销毁线程的开销
- 可以控制并发线程数量,防止资源耗尽
- 提供了丰富的线程管理功能
- 是实际开发中推荐的线程使用方式
总结与对比
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 继承 Thread | 简单直接 | 单继承限制 | 简单的线程任务 |
| 实现 Runnable | 无继承限制,资源共享 | 无法返回结果 | 多线程共享资源 |
| 实现 Callable | 可返回结果,可抛异常 | 用法相对复杂 | 需要获取执行结果 |
| 线程池 | 高效管理线程,复用线程 | 需要理解线程池参数 | 实际开发中推荐使用 |
在实际开发中,推荐使用Runnable接口配合线程池的方式,既避免了单继承限制,又能高效管理线程资源。如果需要获取线程执行结果,则使用Callable接口。
2万+

被折叠的 条评论
为什么被折叠?



