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 * 2N_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() vs shutdownNow() 的区别
  • 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 一个生产环境的配置模板

九、总结

  • 线程池配置不是一成不变的,需要根据压测数据调整
  • 核心原则:有界队列 + 合理拒绝策略 + 明确线程命名