核心线程数需据任务类型设定:CPU密集型设为CPU核数或+1,I/O密集型设为CPU核数×2~4;最大线程数建议≤corePoolSize×2(I/O型可放宽至×4~5);队列须有界以防OOM;keepAliveTime仅作用于非核心线程;threadFactory和handler影响可观测性与容错。

Java线程池的核心参数直接决定其吞吐能力、资源占用和稳定性。合理配置不是套公式,而是结合任务特性、硬件条件与业务容忍度做权衡。
corePoolSize:核心线程数怎么设才不浪费也不卡顿
这是线程池里“常驻部队”的人数。它不会因空闲被回收(除非启用 allowCoreThreadTimeOut),是响应突发任务的第一道防线。
- CPU密集型任务(如图像处理、数值计算):设为
Runtime.getRuntime().availableProcessors()或 +1,避免线程切换开销 - I/O密集型任务(如HTTP调用、数据库查询):可设为 CPU核数 × 2~4,利用等待时间提升并发利用率
- 别盲目设为0——那等于放弃快速响应能力;也别超过物理核数太多——CPU争抢反而拖慢整体速度
maximumPoolSize:最大线程数不是越大越好
它是线程池的“应急扩编上限”。只有当核心线程全忙、任务队列也满了时,才会创建超出 corePoolSize 的非核心线程。
- 建议值通常 ≤ corePoolSize × 2(I/O型可放宽至 × 4~5),防止系统资源(内存、文件句柄、上下文切换)被耗尽
- 若设为 Integer.MAX_VALUE(如
newCachedThreadPool),在高负载下极易触发 OOM - 生产环境务必配合有界队列使用,否则 maximumPoolSize 可能永远达不到——因为任务全堆在无界队列里了
workQueue:队列选错,整个线程池就“假死”
它不是缓存,而是任务调度的“缓冲区+决策器”。不同队列会彻底改变线程池伸缩逻辑:
立即学习“Java免费学习笔记(深入)”;
- ArrayBlockingQueue(有界):容量固定,推荐用于 CPU 密集型场景,强制触发线程扩容或拒绝,防内存溢出
- LinkedBlockingQueue(默认无界):容量为 Integer.MAX_VALUE,适合低吞吐、稳态任务;但高并发下易堆积任务,掩盖线程不足问题
- SynchronousQueue(同步移交):不存储任务,提交即尝试交给空闲线程,失败则创建新线程——适合搭配较大 maximumPoolSize,实现“来活就建线程”弹性模型
keepAliveTime + unit:非核心线程该“站岗”多久
它只约束超出 corePoolSize 的那些线程。空闲超时后,它们会被回收,让线程数回落到核心值。
- 短时间(如 10~30 秒):适合流量波动大、需快速释放资源的场景(如秒杀后缩容)
- 长时间(如 60 秒以上):减少频繁创建/销毁开销,但可能长期占用资源
- 单位必须匹配——写 60L 但用 MILLISECONDS 就等于 60 毫秒,几乎立刻回收,失去意义
threadFactory 和 handler:细节决定可观测性与容错力
这两个参数常被忽略,却是线上排查和降级的关键。
- threadFactory:至少给线程起有意义的名字(如 “order-processor-1”),方便日志定位;可统一设置 UncaughtExceptionHandler,避免异常静默丢失
- handler(拒绝策略):默认 AbortPolicy 直接抛异常,适合强一致性业务;CallerRunsPolicy 让调用方自己执行,可自然限流;DiscardPolicy / DiscardOldestPolicy 适用于允许丢弃的异步通知类任务
不复杂但容易忽略


















