1) 基础概念速览
线程池:线程复用容器,按需/预先创建线程复用执行任务。
优势:降低创建/销毁成本;受控并发;排队与拒绝;可观测与治理。
核心类:
ThreadPoolExecutor
;常见池:Fixed / Cached / Single / Scheduled
。规范:避免直接用
Executors
(默认无界/新建线程,易 OOM)。
七个核心参数corePoolSize
、maximumPoolSize
、keepAliveTime
、unit
、workQueue
、threadFactory
、handler
。
2) 执行与状态原理
调度路径(四步)
< core
→ 新建核心线程直接执行≥ core
→ 入队队列满 且 < max
→ 新建非核心线程否则 → 拒绝策略
状态机RUNNING → SHUTDOWN/STOP → TIDYING → TERMINATED
shutdown()
:温和关闭(不接新单,跑完队列)shutdownNow()
:立刻关闭(中断 + 返回未执行任务)
Worker 复用与 AQS
Worker
执行完首任务后循环getTask()
复用。Worker
继承 AQS 做“忙闲锁”:忙时持锁,空闲无锁 → 只中断空闲线程。
核心 vs 非核心
非核心空闲超时回收;核心默认常驻(可
allowCoreThreadTimeOut(true)
回收)。
3) 队列 & 拒绝策略
队列
ArrayBlockingQueue
:有界、数组;推荐默认。LinkedBlockingQueue
:默认无界,必须限容量。SynchronousQueue
:直传,不排队,利于快速扩到max
。PriorityBlockingQueue
:按优先级(注意避免饿死)。
拒绝策略(4)
Abort
(默认抛异常)CallerRuns
(回压上游)Discard
(丢新)DiscardOldest
(丢最旧)
自定义思路:日志 + 告警 +(可选)落盘/队列重试/降级处理。
4) 实战配置 & 监控排查
参数建议
核心:CPU 密集≈
CPU/CPU+1
;IO 密集≈2×CPU
。最大:核心的
2~5×
(结合时延/切换成本压测微调)。队列:有界;粗略:
容量 ≈ QPS × 平均耗时 × 2
。
监控指标
活跃线程、队列长度、完成数、拒绝数、P95/P99、池状态。
Micrometer → Prometheus/Grafana 告警。
常见问题 & 排查
OOM:无界队列/对象泄漏 → 限容量 + 堆分析。
慢/阻塞:
jstack
定位锁/IO;外部调用设超时。拒绝多:调大容量/限流/降级。
5) Tomcat 线程池 vs JDK 线程池
JDK:先排队后扩线程(稳内存)。
Tomcat:先扩线程到 max 再排队(快出活,适合 Web;关键在自定义
TaskQueue#offer
)。选型:请求链路 → Tomcat Executor;业务异步/批处理 → JDK 池(可多池隔离)。
6) OOM 高发场景与真实案例
6.1 突发流量 + 配置不合理
QPS 暴涨;
core/max
偏小 + 队列无界/过大 → 无限堆积 → OOM。
6.2 消费阻塞(第三方慢/锁/IO 卡住)
线程长期占用,消费速率骤降;队列“温水煮青蛙式”堆积 → OOM。
6.3 任务对象泄漏 + 堆积
任务持有未释放资源(
FileInputStream/Process/ByteBuffer
等),少量堆积即可吃光内存。
6.4 框架隐式线程池
@Async
、MQ 消费者、XXL-Job/Quartz 内部池若无界 → 同样堆积 OOM。
7) 系统性优化方案(落地清单)
有界队列 + 明确拒绝
RejectedExecutionHandler handler = (r, ex) -> { log.error("Pool full: pool={}, active={}, queue={}", ex.getPoolSize(), ex.getActiveCount(), ex.getQueue().size()); // 返回友好提示/HTTP 503 + 告警 };
限流控产:网关/Sentinel;MQ 限速/限批拉取;活动期限流降级。
超时与取消:HTTP/RPC 设 connect/read 超时;
Future.get(timeout)
+cancel(true)
:Future f = executor.submit(task); try { f.get(3, TimeUnit.SECONDS); } catch (TimeoutException e) { f.cancel(true); }
拆池隔离:按任务类型分池(下游慢不拖垮全局)。
监控告警:活跃、队列、拒绝、P99、堆使用率;阈值 ≥80% 告警。
8) 口诀与速记
调度四步:先核心 → 排队 → 扩最大 → 拒绝。
配置三件:有界队列、明确拒绝、监控到位。
避坑两条:别用无界队列;别让外部调用无超时。
9) 面试速问速答(精选)
execute
vssubmit
:无返回 vsFuture
(异常在get()
时抛)。shutdown
vsshutdownNow
:温和 vs 立刻(中断 + 返回未执行)。优先级任务:
PriorityBlockingQueue
+Comparable
(注意饥饿)。取消任务:未执行→
remove(task)
;已执行→任务内响应中断/Future.cancel(true)
。
结论
限产(限流)、限容(有界队列)、限时(超时/取消)、可观测(监控告警),再配合合理扩缩容与任务隔离,线程池才能稳且快。