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) 面试速问速答(精选)
executevssubmit:无返回 vsFuture(异常在get()时抛)。shutdownvsshutdownNow:温和 vs 立刻(中断 + 返回未执行)。优先级任务:
PriorityBlockingQueue+Comparable(注意饥饿)。取消任务:未执行→
remove(task);已执行→任务内响应中断/Future.cancel(true)。
结论
限产(限流)、限容(有界队列)、限时(超时/取消)、可观测(监控告警),再配合合理扩缩容与任务隔离,线程池才能稳且快。
