线程池容量怎么算
线程数要按任务类型核算:CPU 密集型任务的线程数接近核数即可,再多只会增加上下文切换开销;IO 密集型任务在等待期间会让出 CPU,因此线程数可以按等待时间与计算时间的比例放大。核算出线程数之后,还要配队列上限与拒绝策略,配置才算完整。
队列与拒绝策略
无界队列会让过载表现为延迟无上限增长:请求全部堆积,没有任何失败信号,问题要等到超时时刻才暴露。有界队列配合明确的拒绝策略能让过载快速可见,再配合降级返回兜底结果。队列容量还要与上游超时联动,排队时间超过上游超时,任务即使执行完成也无人等待。
核算口径
核算口径
CPU 密集型:线程数 ≈ 核数 + 1
IO 密集型:线程数 ≈ 核数 × (1 + 平均等待 / 平均计算)
# 等待与计算比例靠实测或监控采样确定,不要凭感觉
# 队列选择:有界队列 + 明确拒绝策略(快速失败或降级)配置示例
配置示例
cores = 运行环境可用核数
# 等待与计算比约 9:1 的 IO 密集任务
threads = cores * 10
pool = new ThreadPoolExecutor(
threads, threads, 60, 秒,
new ArrayBlockingQueue(2000), # 有界队列
new AbortPolicy()) # 拒绝策略:快速失败
# 监控:活跃线程数、队列深度、拒绝与超时计数隔离比调参更重要
把所有下游调用放进同一个线程池,任何一个下游变慢都会占满线程,拖垮全部接口。按下游或按业务优先级拆成多个线程池,资源占用与故障影响范围都能被限定在局部,代价是总线程数上升、上下文切换变多,需要按实际容量核算。相比反复调整一个共享池的参数,隔离往往能更快地稳住核心链路。
线程数与队列容量要和上游超时联动:排队时间一旦超过上游超时,任务完成也没有人接收结果,这部分计算就是纯粹的浪费,还会挤压正常任务。