选对线程池需匹配业务特性:cpu密集型用fixedthreadpool(线程数≈cpu核数)或workstealingpool;io密集型宜自定义threadpoolexecutor,设core=2×核数、max=20~50、有界队列+callerrunspolicy;定时任务必用scheduledthreadpoolexecutor;高可靠场景须手动构造,自定义threadfactory和拒绝策略。

选对线程池,不是挑个现成的API用上就行,而是要让线程资源和业务节奏严丝合缝。关键不在“多”或“快”,而在“稳得住、退得巧、看得清”。
CPU密集型任务:控制并发,避免内耗
CPU密集型任务(比如数值计算、图像压缩、规则引擎执行)几乎不等待外部响应,线程一开就满负荷跑。此时线程数过多,反而引发频繁上下文切换,吞吐不升反降。
- 首选 newFixedThreadPool(n),n 设为 CPU 核数或核数+1(如 8 核机器设 8~9)
- 也可用 newWorkStealingPool(),适合可拆分的并行计算(如递归处理树形结构),但不保证执行顺序,也不支持自定义拒绝策略
- 避免用 newCachedThreadPool()——它会无节制创建线程,极易把 CPU 和内存同时打满
IO密集型任务:留足等待空间,但要有界可控
IO密集型任务(如 HTTP 调用、数据库查询、文件读写)大部分时间在等响应,CPU 利用率低。适当增加线程数能提升整体吞吐,但必须配合资源约束。
- 不推荐直接用 newCachedThreadPool():核心线程数为 0,突发流量可能瞬间创建数千线程,耗尽句柄或内存
- 推荐自定义 ThreadPoolExecutor,例如:
• corePoolSize = CPU 核数 × 2(起步值,可结合下游连接池容量调整)
• maximumPoolSize = 20~50(上限需压测验证)
• workQueue = ArrayBlockingQueue(有界队列,容量建议 100~200)
• handler = CallerRunsPolicy(自然反压,防止雪崩)
定时与周期任务:必须专用,不可混用
延时执行、固定频率刷新、心跳检测等场景,对调度精度和稳定性要求高,普通线程池无法满足。
- 必须使用 ScheduledThreadPoolExecutor(通过 newScheduledThreadPool(n) 创建)
- 显式指定线程数(如 n=2 或 n=3),避免单点故障;不要用 newSingleThreadScheduledExecutor 处理关键定时任务
- 它不接受 submit(),只支持 schedule()、scheduleAtFixedRate() 等专用方法
高可靠与可观测场景:绕过 Executors,手动构造
Executors 工厂方法隐藏了关键控制点,生产环境往往需要更精细的掌控。
- 无法设置有意义的 ThreadFactory → 线程名全是 pool-1-thread-1,排查问题无从下手
- 无法自定义拒绝策略 → newFixedThreadPool 默认 AbortPolicy,可能让关键请求静默失败
- 正确做法:直接 new ThreadPoolExecutor(...),并传入带业务前缀的线程工厂、明确的拒绝策略、有界队列
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











