线程池参数配置指南
Executors.newFixedThreadPool()阿里规范不让用,newCachedThreadPool()可能导致 OOM。那么线程池到底该怎么配?本文从源码到生产实践,给出计算公式和配置模板。
一、线程池的 8 个参数
- 1.1 corePoolSize——核心线程数
- 1.2 maximumPoolSize——最大线程数
- 1.3 keepAliveTime——空闲线程存活时间
- 1.4 unit——时间单位
- 1.5 workQueue——工作队列
- 1.6 threadFactory——线程工厂
- 1.7 handler——拒绝策略
- 1.8 参数之间的协作关系——任务提交后的执行流程
二、核心线程数的计算
- 2.1 CPU 密集型:
N_CPU + 1 - 2.2 IO 密集型:
N_CPU * 2或N_CPU / (1 - 阻塞系数) - 2.3 混合型:拆分为两个线程池
- 2.4 动态调整——基于 Runtime.getRuntime().availableProcessors()
三、工作队列选型
- 3.1 SynchronousQueue——无容量,直接提交,配合 large poolSize
- 3.2 LinkedBlockingQueue——无限队列,可能导致 OOM
- 3.3 ArrayBlockingQueue——有界队列,推荐的默认选择
- 3.4 队列长度如何确定——基于请求量和响应时间
四、拒绝策略的 4 种选择
- 4.1 AbortPolicy——抛异常,保留现场
- 4.2 CallerRunsPolicy——调用者线程执行,天然的限流
- 4.3 DiscardPolicy——静默丢弃
- 4.4 DiscardOldestPolicy——丢弃最旧的任务
- 4.5 自定义策略——持久化到数据库/消息队列
五、线程工厂的规范
- 5.1 自定义线程命名——便于排查问题
- 5.2 设置 daemon 线程
- 5.3 设置线程优先级和异常处理器
六、线程池的生命周期
- 6.1 RUNNING → SHUTDOWN → STOP → TIDYING → TERMINATED
- 6.2
shutdown()vsshutdownNow()的区别 - 6.3 优雅停机——
awaitTermination()
七、Executors 为什么不推荐
- 7.1
newFixedThreadPool——无界队列 OOM 风险 - 7.2
newCachedThreadPool——无界线程数 OOM 风险 - 7.3
newSingleThreadExecutor——同样是无界队列 - 7.4 正确做法——使用
ThreadPoolExecutor构造器
八、监控与调优
- 8.1 需要监控的指标——活跃线程数、队列大小、任务完成数、拒绝数
- 8.2 线程池的
beforeExecute()/afterExecute()钩子 - 8.3 动态调整线程池参数——美团 DynamicTp
- 8.4 一个生产环境的配置模板
九、总结
- 线程池配置不是一成不变的,需要根据压测数据调整
- 核心原则:有界队列 + 合理拒绝策略 + 明确线程命名
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!