线程池
线程池是 Java 并发编程中最重要的工具之一,它能够有效管理线程资源,提高应用程序的性能和稳定性。
1. 为什么使用线程池
| 优势 | 说明 |
|---|---|
| 降低资源消耗 | 重用已创建的线程,避免频繁创建销毁 |
| 提高响应速度 | 任务到达时无需等待线程创建 |
| 便于管理 | 统一分配、调优和监控 |
| 控制并发数 | 防止无限制创建线程导致系统崩溃 |
2. 创建线程池
2.1 Executors 工厂方法(不推荐)
java
import java.util.concurrent.*;
// 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(10);
// 缓存线程池(线程数不固定)
ExecutorService cachedPool = Executors.newCachedThreadPool();
// 单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();
// 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(5);⚠️ 阿里规范:不推荐使用 Executors 创建线程池,因为可能导致 OOM。
2.2 ThreadPoolExecutor(推荐)
java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // corePoolSize: 核心线程数
10, // maximumPoolSize: 最大线程数
60L, // keepAliveTime: 空闲线程存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(100), // 工作队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);3. 七大核心参数
java
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 空闲线程存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 工作队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)3.1 corePoolSize(核心线程数)
| 属性 | 说明 |
|---|---|
| 作用 | 线程池中始终保持存活的线程数量 |
| 默认行为 | 核心线程创建后不会被回收 |
配置建议:
- CPU 密集型:
corePoolSize = CPU核心数 + 1 - IO 密集型:
corePoolSize = CPU核心数 × 2
java
int cpuCores = Runtime.getRuntime().availableProcessors();3.2 maximumPoolSize(最大线程数)
| 属性 | 说明 |
|---|---|
| 作用 | 线程池允许创建的最大线程数量 |
| 约束 | 必须 >= corePoolSize |
3.3 keepAliveTime(空闲存活时间)
| 属性 | 说明 |
|---|---|
| 作用 | 非核心线程空闲时的存活时间 |
| 生效范围 | 默认只对非核心线程生效 |
3.4 workQueue(工作队列)
| 队列类型 | 特点 | 适用场景 |
|---|---|---|
ArrayBlockingQueue | 有界队列 | 推荐,需限制队列大小 |
LinkedBlockingQueue | 默认无界 | 需设置容量,防止 OOM |
SynchronousQueue | 不存储元素 | 快速响应场景 |
PriorityBlockingQueue | 优先级队列 | 任务有优先级区分 |
3.5 threadFactory(线程工厂)
java
ThreadFactory customFactory = new ThreadFactory() {
private final AtomicInteger counter = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("order-pool-" + counter.getAndIncrement());
thread.setDaemon(false);
return thread;
}
};3.6 handler(拒绝策略)
| 策略 | 行为 |
|---|---|
AbortPolicy | 抛出异常(默认) |
CallerRunsPolicy | 调用者线程执行 |
DiscardPolicy | 静默丢弃 |
DiscardOldestPolicy | 丢弃最老任务 |
4. 工作流程
提交任务
│
▼
┌────────────────┐
│ 线程数 < 核心数?│
└────────────────┘
│ │
YES NO
│ │
▼ ▼
创建核心线程 ┌────────────┐
执行任务 │ 队列未满? │
└────────────┘
│ │
YES NO
│ │
▼ ▼
任务入队 ┌──────────────┐
等待执行 │ 线程数 < 最大?│
└──────────────┘
│ │
YES NO
│ │
▼ ▼
创建非核心 执行拒绝
线程执行 策略5. 核心线程生命周期管理
5.1 allowCoreThreadTimeOut
java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, 10, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100)
);
// 开启核心线程超时回收
executor.allowCoreThreadTimeOut(true);
// 此时所有线程空闲60秒后都会被回收
// 线程池可能缩减到 0 个线程| 场景 | 是否开启 |
|---|---|
| 任务频繁 | ❌ 关闭 |
| 任务间隔长 | ✅ 开启 |
5.2 prestartAllCoreThreads
java
// 预启动所有核心线程
int started = executor.prestartAllCoreThreads();
// 预启动一个核心线程
boolean success = executor.prestartCoreThread();使用场景:Web 应用启动时预热,避免首批请求冷启动延迟。
6. 提交任务
java
ExecutorService executor = Executors.newFixedThreadPool(5);
// execute:无返回值
executor.execute(() -> {
System.out.println("执行任务");
});
// submit:有返回值
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "任务结果";
});
String result = future.get(); // 阻塞获取结果7. 关闭线程池
java
// 优雅关闭:不再接受新任务,等待已提交任务完成
executor.shutdown();
// 立即关闭:尝试中断正在执行的任务
List<Runnable> notExecuted = executor.shutdownNow();
// 等待关闭完成
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}8. 最佳实践
8.1 生产环境配置示例
java
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor orderProcessPool() {
int cpuCores = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
cpuCores * 2, // 核心线程数
cpuCores * 4, // 最大线程数
60L, TimeUnit.SECONDS, // 空闲存活时间
new ArrayBlockingQueue<>(500), // 有界队列
new ThreadFactoryBuilder()
.setNameFormat("order-pool-%d")
.build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 预热线程池
executor.prestartAllCoreThreads();
return executor;
}
}8.2 监控线程池
java
ThreadPoolExecutor executor = ...;
// 监控指标
System.out.println("核心线程数: " + executor.getCorePoolSize());
System.out.println("当前线程数: " + executor.getPoolSize());
System.out.println("活跃线程数: " + executor.getActiveCount());
System.out.println("历史最大线程数: " + executor.getLargestPoolSize());
System.out.println("已完成任务数: " + executor.getCompletedTaskCount());
System.out.println("队列大小: " + executor.getQueue().size());