一、为什么不推荐 Executors
阿里开发手册明确禁止使用Executors 创建线程池,原因是:
newFixedThreadPool使用无界队列LinkedBlockingQueue,可能 OOMnewCachedThreadPool最大线程数为Integer.MAX_VALUE,可能创建海量线程
new ThreadPoolExecutor(...)。
二、七个核心参数
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
三、任务提交后的执行流程
提交任务
├─ 当前线程数 < corePoolSize → 创建核心线程执行
├─ 核心线程已满 → 任务入队
│ └─ 队列已满 且 线程数 < maximumPoolSize → 创建非核心线程
│ └─ 线程数已达 maximumPoolSize → 执行拒绝策略
关键认知:队列满了才会创建非核心线程,而不是核心线程满了就创建。
四、队列怎么选
| 队列 | 特点 | 风险 | | --- | --- | --- | | ArrayBlockingQueue | 有界数组队列 | 需合理设置容量 | | LinkedBlockingQueue | 默认无界 | 可能 OOM | | SynchronousQueue | 不存储元素 | 需配合大 maxPoolSize | | PriorityBlockingQueue | 优先级 | 无界 |五、线程数怎么算
// CPU 密集型:线程数 ≈ CPU 核数 + 1
int cpuCount = Runtime.getRuntime().availableProcessors();
// IO 密集型:线程数 ≈ CPU 核数 * (1 + 等待时间/计算时间)
// 经验值:CPU 核数 * 2
六、生产配置示例
@Bean("orderExecutor")
public ThreadPoolExecutor orderExecutor() {
ThreadFactory factory = new ThreadFactoryBuilder()
.setNameFormat("order-pool-%d")
.setUncaughtExceptionHandler((t, e) -> log.error("线程异常", e))
.build();
return new ThreadPoolExecutor(
8, 16, 60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2000),
factory,
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
拒绝策略选择:
AbortPolicy:抛异常(默认),适合关键任务CallerRunsPolicy:让提交者自己执行,天然限流(推荐)DiscardPolicy:静默丢弃,慎用DiscardOldestPolicy:丢弃队头,慎用
七、记得给线程命名
// 反例:pool-1-thread-1,出问题时无法定位
// 正例:order-pool-3,一眼看出是哪个业务池
评论(2)