线程池大小需按任务类型确定:cpu密集型设为核数+1,io密集型依等待时间占比估算,并分池处理混合任务;队列须有界,拒绝策略选abortpolicy或callerrunspolicy。

线程池大小不能只看CPU核数,得先判断任务类型,再结合资源瓶颈和实际表现来定。
CPU密集型任务:核心数+1是底线
这类任务几乎不等IO,CPU持续满负荷,比如图像压缩、科学计算、大量循环运算。线程数超过逻辑核数,只会增加上下文切换开销,拖慢整体吞吐。
- 推荐核心线程数 = Runtime.getRuntime().availableProcessors() + 1
- +1 是为应对偶尔的缺页中断或GC暂停,留一个备用线程保障调度连续性
- maximumPoolSize 通常设为与 corePoolSize 相同,避免动态扩容引入不确定性
- 队列建议用有界 LinkedBlockingQueue(如容量100~1000),拒绝策略选 AbortPolicy,让问题暴露得早
IO密集型任务:看等待时间占比,不是拍脑袋翻倍
HTTP调用、数据库查询、文件读写这些任务,90%以上时间在等响应,CPU空闲。关键不是“能开多少线程”,而是“有多少并发请求正在等”。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 理论公式:corePoolSize ≈ CPU核数 × (1 + 平均等待时间 / 平均CPU工作时间)
- 举例:8核机器,一次DB查询平均耗时200ms,其中CPU处理仅5ms → 8 × (1 + 200/5) = 328 —— 这个数只是起点,不能直接用
- 更实用做法:用峰值QPS × 平均IO耗时(秒)估算瞬时并发需求,再加20%~50%缓冲
- 必须检查下游瓶颈:DB连接池最大连接数、HTTP客户端最大路由连接数、网卡带宽、服务端限流阈值——线程再多,卡在连接池就全堵住
混合型任务:别硬凑一个池,分池隔离最稳妥
一个接口既做加解密(CPU型)又查三次库(IO型),统一配池必然顾此失彼。CPU型任务可能被IO阻塞线程长期排队,而IO型又因线程不足堆积。
- 优先按主责拆分:计算类走CPU优化池(corePoolSize = 核数+1),远程调用走IO优化池(corePoolSize = 核数×2~3)
- 用 CompletableFuture.supplyAsync(task, executor) 显式指定执行器,不依赖默认线程池
- 若必须共用,保守按IO型配置,但必须监控 getActiveCount() 和 getQueue().size() —— 持续高位说明CPU型任务已在排队饿死
参数配对比公式更重要:队列+拒绝策略决定真实行为
再合理的线程数,配错队列和拒绝策略也白搭。
- 用 LinkedBlockingQueue 且无界 → maximumPoolSize 形同虚设,永远只启 corePoolSize 个线程
- 用 SynchronousQueue → 新任务直接触发扩容,直到达 maximumPoolSize,再提交就触发拒绝策略
- 拒绝策略别用默认的 DiscardPolicy(静默丢弃),选 AbortPolicy(抛异常)或 CallerRunsPolicy(由提交线程自己执行),更容易发现容量不足
- workQueue 必须有界,防止OOM;常见设为 1000 或根据平均积压量×2设定
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










