一、Java 中创建线程的四种主要方式
| 方式 |
简述 |
适用场景 |
| 继承 Thread 类 |
重写 run() 方法,直接创建线程 |
简单场景、临时任务 |
| 实现 Runnable 接口 |
将任务与线程分离 |
推荐方式,任务更灵活 |
| 实现 Callable 接口 |
支持返回值和异常 |
异步任务,需要结果的场景 |
| 使用线程池(Executor) |
统一管理线程、复用资源 |
高并发任务、后台服务等 |
二、方式一:继承 Thread 类
2.1 示例代码
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread by extending Thread class");
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
2.2 特点
- 简单直观,适合快速实验。
- 不能再继承其他类(因为 Java 单继承)。
三、方式二:实现 Runnable 接口
3.1 示例代码
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread by implementing Runnable");
}
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
3.2 Lambda 简写(Java 8+)
Thread thread = new Thread(() -> System.out.println("Runnable with Lambda"));
thread.start();
3.3 特点
- 更推荐的方式:任务与线程解耦,利于代码复用。
- 可避免继承限制(类可同时实现多个接口)。
四、方式三:实现 Callable 接口 + FutureTask
4.1 示例代码
import java.util.concurrent.*;
public class MyCallable implements Callable<String> {
@Override
public String call() {
return "Result from Callable";
}
public static void main(String[] args) throws Exception {
Callable<String> callable = new MyCallable();
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
String result = futureTask.get();
System.out.println(result);
}
}
4.2 特点
- 支持返回值(
Future.get() 获取结果)。
- 支持异常抛出。
- 常用于需要任务结果的异步处理。
五、方式四:使用线程池(推荐)
5.1 创建线程池的方式
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> {
System.out.println("Task in thread pool");
});
executor.shutdown();
5.2 使用 Callable + Future 获取结果
Callable<String> task = () -> "Hello from Callable";
Future<String> future = executor.submit(task);
System.out.println(future.get());
5.3 推荐使用 ThreadPoolExecutor 构造方法
ExecutorService pool = new ThreadPoolExecutor(
2, 4, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
5.4 特点
- 更强的任务调度与资源控制能力。
- 支持线程复用,减少资源消耗。
- 支持拒绝策略、线程工厂、任务统计等。
六、方式五(拓展):使用定时任务线程池 ScheduledExecutorService
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.scheduleAtFixedRate(() -> {
System.out.println("Running scheduled task...");
}, 0, 5, TimeUnit.SECONDS);
七、各方式对比总结
| 方式 |
是否支持返回值 |
是否支持异常处理 |
推荐度 |
特点简述 |
| 继承 Thread |
否 |
否 |
★★☆☆☆ |
简单但耦合度高 |
| 实现 Runnable |
否 |
否 |
★★★★☆ |
灵活,任务与线程分离 |
| 实现 Callable |
✅ |
✅ |
★★★★★ |
支持异步、有返回值 |
| Executor 线程池 |
✅ |
✅ |
★★★★★ |
资源可控,适用于生产级应用 |
| ScheduledExecutor |
✅ |
✅ |
★★★★☆ |
定时/周期性任务 |
八、最佳实践建议
- 永远不要使用
new Thread() 启动线程处理业务逻辑。
- 使用线程池统一管理线程生命周期。
- 对于需要结果的任务,使用
Callable + Future。
- 对于定期任务,使用
ScheduledExecutorService。
- Java 8 以后建议使用 Lambda 简化线程任务代码。
- 在线程执行中注意异常捕获、资源释放与日志记录。
九、附:线程池参数详解表
| 参数名 |
含义 |
| corePoolSize |
核心线程数 |
| maximumPoolSize |
最大线程数 |
| keepAliveTime |
非核心线程空闲多久被回收 |
| workQueue |
任务队列(如:LinkedBlockingQueue) |
| threadFactory |
自定义线程工厂 |
| handler |
拒绝策略(Abort、CallerRuns等) |
十、参考文档与资料
所有评论(0)