ExecutorService怎么用
ExecutorService 是 Java 中用于管理和调度线程的核心接口,位于 java.util.concurrent 包下。它比直接使用 Thread 更优雅、可控,适合线程池、任务执行、并发控制等场景。
下面从 概念 → 常用方法 → 使用示例 → 关闭线程池 → 常见用法模式 给你一个完整说明。
一、为什么要用 ExecutorService?
不用它时你可能这样写:
new Thread(() -> {
// do something
}).start();
问题:
- 线程创建销毁开销大
- 不好控制线程数量
- 不好获取返回结果
- 不好统一关闭
✅ ExecutorService 解决这些问题。
二、创建 ExecutorService
1️⃣ 常用创建方式(推荐)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
ExecutorService executor = Executors.newFixedThreadPool(5);
常见线程池类型:
| 方法 | 说明 |
|---|---|
newFixedThreadPool(n) |
固定大小线程池 |
newCachedThreadPool() |
可缓存线程池(线程可复用) |
newSingleThreadExecutor() |
单线程池 |
newScheduledThreadPool(n) |
支持定时/周期任务 |
三、提交任务(最核心)
1️⃣ 提交无返回值的任务(Runnable)
executor.execute(() -> {
System.out.println("任务执行中");
});
✅ 无返回值
✅ 不能抛受检异常
2️⃣ 提交有返回值的任务(Callable)
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
Callable task = () -> {
Thread.sleep(1000);
return "执行结果";
};
Future future = executor.submit(task);
String result = future.get(); // 阻塞等待结果
System.out.println(result);
✅ 可返回结果
✅ 可抛异常
四、关闭 ExecutorService(非常重要)
1️⃣ 优雅关闭(推荐)
executor.shutdown(); // 不再接受新任务
或设置超时:
executor.awutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
2️⃣ 立即关闭(强制)
executor.shutdownNow();
⚠ 不推荐随意使用,可能中断正在执行的任务。
五、完整示例
✅ 示例 1:批量执行任务
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
int taskId = i;
executor.execute(() -> {
System.out.println("任务 " + taskId + " 执行");
});
}
executor.shutdown();
✅ 示例 2:获取多个任务结果
ExecutorService executor = Executors.newFixedThreadPool(3);
List> futures = new ArrayList<>();
for (int i = 0; i < 5; i++) {
futures.add(executor.submit(() -> {
Thread.sleep(500);
return 1;
}));
}
int sum = 0;
for (Future f : futures) {
sum += f.get();
}
System.out.println(sum);
executor.shutdown();
六、常见使用模式
✅ 模式 1:Web 服务后台任务
executor.submit(() -> {
// 发邮件、写日志、异步处理
});
✅ 模式 2:并发计算
Future f1 = executor.submit(() -> calc1());
Future f2 = executor.submit(() -> calc2());
int r1 = f1.get();
int r2 = f2.get();
七、注意事项(面试常问)
✅ 线程池大小怎么定?
- CPU 密集型:
CPU 核心数 + 1 - IO 密集型:
CPU 核心数 * 2或更多
✅ execute 和 submit 区别?
| 对比 | execute | submit |
|---|---|---|
| 返回值 | 无 | Future |
| 异常 | 直接抛出 | 封装在 Future |
| 任务类型 | Runnable | Runnable / Callable |
八、总结一句话
ExecutorService 是 Java 中管理线程池、执行异步任务、控制并发的核心工具。
如果你愿意,我可以:
- 给你讲 线程池底层原理
- 对比 ThreadPoolExecutor 参数
- 结合 Spring @Async
- 来一个 真实业务场景示例
你想看哪一个?