Skip to content
掌握度

小林无对应内容。对比 JavaGuide 线程池详解与最佳实践、二哥《24 张图弄懂线程池》《为什么阿里禁用 Executors》与面渣逆袭《并发编程》(侧边栏进入)。

多版对比 ​

七参数与执行流程,三方一致​:corePoolSize、maximumPoolSize、keepAliveTime、workQueue、threadFactory、handler;提交顺序是「核心线程 → 队列 → 非核心线程 → 拒绝策略」。面渣的银行营业厅类比最好背(柜台=核心线程、等候区=队列、开新柜台=扩到最大、爆满拒绝)。

​「为什么禁用 Executors」,三家互补​:二哥给出三种内置池各自的 OOM 机制——Fixed/Single 用无界 LinkedBlockingQueue 堆任务、Cached/Scheduled 无限扩线程,并附真实 OOM 测试代码(全场独有);JG 同口径并按 Executor 框架梳理;面渣只给结论。

参数怎么设,公式一致但深度不同​:CPU 密集 N+1、IO 密集 Ncpu × Ucpu × (1 + W/C)——三家都给;JG 补 Little's Law(L = λ × T)视角并强调公式只是起点、必须压测​;二哥讲源码级原理——Worker 继承 AQS,runWorker 循环取任务实现线程复用​、五种状态、prestartAllCoreThreads 预热。

生产治理,JG 独有且最值钱​:CallerRunsPolicy 的背压局限(会阻塞提交线程拖垮上游);动态调参 setter 的生效细节(队列容量不可改、调整顺序有讲究);Hippo4j / Dynamic TP 动态线程池;虚拟线程的适用边界。面渣补动态改参两条路(配置中心下发 / 自定义 ThreadPoolExecutor,引美团实践)。

最优题解 ​

线程池解决两个问题:复用线程省创建销毁开销、统一管控并发度防资源打爆。七个核心参数里,执行顺序是关键——提交任务先加核心线程,满了进队列,队列满了才扩到最大线程数,再满走拒绝策略;这也解释了为什么 FixedThreadPool 有 OOM 风险(无界队列永不触发扩容和拒绝)。所以阿里规范禁止 Executors,要求手动 new ThreadPoolExecutor 并给有界队列 + 明确的拒绝策略。

参数怎么定:CPU 密集约 N+1,IO 密集按 Ncpu × 利用率 × (1 + 等待/计算) 估,但公式只是起点,必须压测校准。生产上线程池要可观测(活跃数、队列深度、拒绝数)和可调参——队列容量和线程数支持运行时调整(动态线程池),拒绝策略按业务选:可丢失的用 Discard,不能丢的用 CallerRuns 并接受它对上游的背压。

追问链 ​

追问:核心线程能被回收吗?​ 参考答:默认不能,一直存活取任务;allowCoreThreadTimeOut(true) 可以让核心线程也超时回收——流量低谷释放资源时用。

追问:任务抛异常了线程会怎样?​ 参考答:execute 提交时异常会直接抛出并终结该线程,线程池重建补位,但异常就被吞了;submit 返回 Future,异常存在 Future 里,调用 get 才拿到——所以要么用 submit 并处理 Future,要么给任务套 try-catch 或设置 UncaughtExceptionHandler。

我的理解 ​

这题的答法梯度:背七参数是及格,说清「队列先于扩容」的顺序和 OOM 机制是良好,主动讲动态调参 + 背压 + 可观测是优秀——JG 的最佳实践篇是主要弹药。二哥的「Worker 继承 AQS 实现复用」是被追问到源码层时的杀手锏;面渣的银行类比用来开场。三家公式一致说明这是共识区,答公式不如答「我会压测校准」。

本站仅供个人学习使用,请勿外传