连载中 15/21

线程池(下):参数怎么定、拒绝策略选哪个、怎么动态调

2026-10-30 · 27 阅读 · 0 评论 · 0 赞

四种拒绝策略,各有各的哲学

AbortPolicy——默认,直接抛 RejectedExecutionException,让提交方知道「满了」,配合 try-catch 做降级;CallerRunsPolicy——谁提交谁自己跑:提交线程被占住干活,上游自然就慢了,相当于内置反压,适合允许慢但不许丢的任务;DiscardPolicy——静默丢弃,最危险,丢了你都不知道;DiscardOldestPolicy——丢队列里最老的腾位,适合「新数据比旧数据有价值」的场景,比如行情推送。选型一句话:宁可吵着失败,不要安静地丢——抛异常至少留下排查线索。

参数怎么定:公式是起点,压测是终点

经典公式:CPU 密集型任务,线程数约等于核数 + 1(补位防偶发阻塞);IO 密集型,线程数约等于核数 × (1 + 等待时间/计算时间)。公式给的是起点——真实系统的等待比、上下文切换成本,公式里都没有,最终以压测为准。另外队列大小要和拒绝策略联动:队列太深,堆积的任务等到处理时可能早已超时,白占内存——某些场景「先拒掉」比「先存着」更负责。

监控:线程池必须可观测

线程池自带关键指标,接入监控定期采集:getActiveCount() 活跃线程数、getQueue().size() 积压任务数、getCompletedTaskCount() 累计完成数。积压持续上涨就是容量告急的前兆——比 OOM 早上好几个小时。

动态调参:不用重启

ThreadPoolExecutor 提供运行时 setter:setCorePoolSize、setMaximumPoolSize 实时生效——新值大于旧值会预创建线程补位,小于则多余空闲线程按超时回收。把它和配置中心串起来,就是「大促调大、平时调回」的动态线程池,美团的技术实践文章讲得很细。核心公式化记忆:参数外置 + 监控 + 运行时 setter。

关闭:温和与粗暴

shutdown() 温和:不再收新任务,已提交的跑完才散伙;shutdownNow() 粗暴:立刻中断所有线程,返回还没来得及跑的任务列表给你善后。线程池不用了必须关——池里的线程默认非守护,只要有一个池没关,JVM 就退不出去。应用里通常有容器生命周期托管,但写工具类、跑批脚本时,这个坑特别常见。

线程池篇完。下一篇并发容器第一主角 ConcurrentHashMap——从 JDK 7 的分段锁到 JDK 8 的 CAS 加 synchronized,看锁的粒度怎么一步步做细。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#Java#线程池#拒绝策略#动态调参#JUC

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10113 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9876 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9306 阅读 · 21 评论 · 287 赞