ExecutorService 是 Java 并发编程中管理线程池的核心工具。下面从设计原则、常见用法、配置建议、陷阱与最佳实践几个维度,给你一份实战级最佳实践总结。
Executors.*)ExecutorService executor = Executors.newFixedThreadPool(10);
原因:
LinkedBlockingQueue)→ 可能 OOMThreadPoolExecutorExecutorService executor = new ThreadPoolExecutor(
4, // corePoolSize
8, // maximumPoolSize
60L, TimeUnit.SECONDS, // keepAliveTime
new ArrayBlockingQueue<>(100), // 有界队列
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
| 任务类型 | 建议 |
|---|---|
| CPU 密集型 | CPU核心数 + 1 |
| IO 密集型 | CPU核心数 * 2 或更多 |
| 混合型 | 拆分线程池 |
int cores = Runtime.getRuntime().availableProcessors();
✅ 必须有界
new ArrayBlockingQueue<>(500)
❌ 无界队列 = 风险
| 策略 | 场景 |
|---|---|
AbortPolicy(默认) |
重要任务,快速失败 |
CallerRunsPolicy |
削峰、保护系统 |
| 自定义 | 记录日志 / 落盘 / 报警 |
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.warn("task rejected");
}
}
executor.shutdown(); // 不再接受新任务
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
executor.shutdownNow(); // 强制关闭
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
| 方法 | 是否关心结果 |
|---|---|
execute() |
不关心 |
submit() |
关心 |
invokeAll() |
批量 |
invokeAny() |
取最快 |
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "ok";
});
try {
String result = future.get(2, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
}
✅ 永远给 get() 设置超时
executor.submit(() -> {
throw new RuntimeException("error");
});
异常会被吞掉!
executor.submit(() -> {
try {
doWork();
} catch (Exception e) {
log.error("task error", e);
}
});
Future<?> f = executor.submit(task);
f.get(); // 会抛异常
new ThreadFactory() {
private final AtomicInteger count = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "biz-pool-" + count.getAndIncrement());
}
}
或使用 Guava:
ThreadFactory factory = new ThreadFactoryBuilder()
.setNameFormat("order-pool-%d")
.build();
| 反模式 | 说明 |
|---|---|
| 一个 JVM 一个线程池 | 不同业务混在一起 |
| 任务无限阻塞 | 耗尽线程 |
| 提交后不管 | 丢 Future |
| 线程池不关闭 | 应用无法优雅退出 |
用 Timer |
用 ScheduledExecutorService |
ExecutorService ioExecutor; // IO 任务
ExecutorService cpuExecutor; // 计算任务
ExecutorService asyncExecutor; // 异步通知
✅ 不同 SLA 的任务,必须隔离线程池
使用
ThreadPoolExecutor创建线程池,
设置合理的核心线程数、有界队列和拒绝策略,
正确关闭线程池,
提交任务时处理异常并设置超时,
不同业务使用不同线程池。
如果你愿意,我可以:
直接告诉我你的使用场景即可。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。