线程池参数需按任务类型精准配置:cpu密集型设corepoolsize为cpu核数+1,io密集型设为cpu核数×2~4;maximumpoolsize设为核心线程数的2~3倍作应急上限;workqueue首选有界arrayblockingqueue;拒绝策略推荐callerrunspolicy或自定义告警重试。

线程池不是配得越多越快,而是配得刚好才稳。核心参数不是随便填的数字,而是你对系统容量、任务特性和退化路径的明确表达。
corePoolSize:按任务类型定“常驻兵力”
它代表线程池里永远留着的线程数,不干活也占着位置。配错会直接拖慢响应或浪费资源。
- CPU密集型(如加解密、图像处理):设为 CPU核数 + 1。8核机器就设8~9。线程再多只会增加上下文切换开销,不提升吞吐。
- IO密集型(如HTTP调用、DB查询):设为 CPU核数 × 2 ~ 4。因为线程大部分时间在等,多开几个能更好利用空闲CPU。
- 混合型任务:优先拆成两个线程池——一个专跑计算,一个专跑IO。避免慢IO把快计算卡死。
maximumPoolSize:设好“应急上限”,防雪崩
它不是用来日常运行的,而是扛突发流量的“预备队”。超过这个数,线程池就不再扩容,转而走拒绝策略。
- 常规场景:设为核心线程数的2~3倍,比如 core=8,max=16~24。
- 强依赖下游的场景(如调支付网关):必须结合下游限流能力来设。别让线程池成了压垮对方的“放大器”。
- 容器化环境(K8s):要同步考虑Pod内存限制。线程太多+队列太大,容易OOM被Kill。
workQueue:选对队列,就是选好缓冲策略
队列不是越大越好,它是任务积压的第一道缓冲区,也决定了拒绝策略何时触发。
- ArrayBlockingQueue(有界):推荐首选。比如容量设1000,能防止任务无限堆积吃光内存,也迫使你正视峰值压力。
- LinkedBlockingQueue(无界,默认Integer.MAX_VALUE):慎用。表面“永不拒绝”,实际可能把JVM内存撑爆,故障时难以定位。
- SynchronousQueue(无缓存):适合高吞吐、低延迟场景,任务直接交由空闲线程处理,不排队。但要求maximumPoolSize足够大,否则极易触发拒绝。
RejectedExecutionHandler:定义系统“扛不住时怎么退”
拒绝策略不是兜底摆设,而是关键业务的容错开关。默认AbortPolicy(抛异常)在线上往往不合适。
- CallerRunsPolicy:让提交任务的线程自己执行。能自然降速,适合非实时但不可丢的任务(如日志聚合)。
- DiscardOldestPolicy:丢掉队列里最老的任务,腾位置给新任务。适合消息类场景,新数据比旧数据重要。
- 高一致性要求场景(如订单创建):建议自定义策略,把拒绝任务写入重试队列或发告警,而不是静默丢弃。
参数不是一次配完就一劳永逸。上线后必须监控活跃线程数、队列堆积量、拒绝率,再结合压测和真实流量动态调优。稳,才是线程池真正的KPI。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











