线程池 ThreadPoolExecutor
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建自定义线程工厂
ThreadFactory customeThreadFactory = new ThreadFactory() {
private final AtomicInteger count = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("自定义线程-" + count.getAndIncrement());
return thread;
}
};
ThreadPoolExecutor executor = new ThreadPoolExecutor(
1, // 核心线程数
2, // 最大线程数
60L, // 临时线程空闲存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2),// 队列容量
customeThreadFactory,
new ThreadPoolExecutor.CallerRunsPolicy()// 触发拒绝策略(CallerRunsPolicy)
);
// 提交任务
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
return taskId;
});
}
// 关闭线程池
executor.shutdown();
}
}
处理流程:
- 第1个任务:
创建核心线程处理(1个核心线程) - 第2、3个任务:
进入队列等待(队列容量2个) - 第4个任务:
创建临时线程处理(最大线程数2 - 核心线程数1 = 1个临时线程) - 第5个任务:
触发拒绝策略(CallerRunsPolicy)
在调用者线程中执行
临时线程:
keepAliveTime = 60L // 临时线程空闲存活时间
- 临时线程在空闲超过60秒后会被回收。
- 核心线程默认不回收。
- 可以通过
allowCoreThreadTimeOut(true)
允许回收核心线程。
如何设置合适的参数:
如何设置合适的参数
- 核心线程数设置考虑因素:
- CPU密集型:通常设置为CPU核心数+1
- IO密集型:可以设置为CPU核心数*2
- 混合型:CPU核心数(1+平均等待时间/平均工作时间)
- 最大线程数设置考虑因素:
- 系统内存大小
- 任务的响应时间要求
- 任务的类型(CPU密集或IO密集)
- 示例配置
// CPU密集型配置
int cpuCores = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor cpuIntensiveExecutor = new ThreadPoolExecutor(
cpuCores + 1, // 核心线程数
cpuCores + 1, // 最大线程数
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000)
);
// IO密集型配置
ThreadPoolExecutor ioIntensiveExecutor = new ThreadPoolExecutor(
cpuCores * 2, // 核心线程数
cpuCores * 4, // 最大线程数
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2000)
);
核心线程用于处理正常负载。
临时线程用于处理突发负载。
参数设置需要根据实际业务场景调整和测试。
CallerRunsPolicy 的作用:
- 流量控制
- 当线程池满载时,让调用者自己执行任务。
- 这会降低任务提交的速度。
- 起到自然的背压作用。
- 防止任务丢失
- 不像 DiscardPolicy 直接丢弃任务。
- 不像 AbortPolicy 抛出异常。
- 确保任务最终会被执行。
- 优缺点
- 优点:不会丢失任务。
- 缺点:可能会影响调用者线程的响应时间。
评论