线程池面试最容易出现一种情况:七个参数都能背,但一问任务提交后到底怎么流转,就开始乱。
线程池不是"提前创建几个线程"这么简单。它真正解决的是三个问题:
- 复用线程,减少频繁创建和销毁的成本。
- 控制并发数量,避免线程无限增长拖垮机器。
- 给任务排队、拒绝、降级提供明确策略。
ThreadPoolExecutor 七个核心参数
先看构造方法:
java
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
这七个参数可以按"线程、队列、拒绝"三类记。
| 参数 | 含义 |
|---|---|
corePoolSize |
核心线程数 |
maximumPoolSize |
最大线程数,包含核心线程和救急线程 |
keepAliveTime |
救急线程空闲多久后回收 |
unit |
时间单位 |
workQueue |
阻塞队列,没有空闲核心线程时任务排队 |
threadFactory |
线程工厂,用来设置线程名、是否守护线程等 |
handler |
拒绝策略,线程和队列都满时触发 |
#mermaid-svg-y7dNiHD3wCBP0Fqp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-y7dNiHD3wCBP0Fqp .error-icon{fill:#552222;}#mermaid-svg-y7dNiHD3wCBP0Fqp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-y7dNiHD3wCBP0Fqp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .marker.cross{stroke:#333333;}#mermaid-svg-y7dNiHD3wCBP0Fqp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-y7dNiHD3wCBP0Fqp p{margin:0;}#mermaid-svg-y7dNiHD3wCBP0Fqp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .cluster-label text{fill:#333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .cluster-label span{color:#333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .cluster-label span p{background-color:transparent;}#mermaid-svg-y7dNiHD3wCBP0Fqp .label text,#mermaid-svg-y7dNiHD3wCBP0Fqp span{fill:#333;color:#333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .node rect,#mermaid-svg-y7dNiHD3wCBP0Fqp .node circle,#mermaid-svg-y7dNiHD3wCBP0Fqp .node ellipse,#mermaid-svg-y7dNiHD3wCBP0Fqp .node polygon,#mermaid-svg-y7dNiHD3wCBP0Fqp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-y7dNiHD3wCBP0Fqp .rough-node .label text,#mermaid-svg-y7dNiHD3wCBP0Fqp .node .label text,#mermaid-svg-y7dNiHD3wCBP0Fqp .image-shape .label,#mermaid-svg-y7dNiHD3wCBP0Fqp .icon-shape .label{text-anchor:middle;}#mermaid-svg-y7dNiHD3wCBP0Fqp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-y7dNiHD3wCBP0Fqp .rough-node .label,#mermaid-svg-y7dNiHD3wCBP0Fqp .node .label,#mermaid-svg-y7dNiHD3wCBP0Fqp .image-shape .label,#mermaid-svg-y7dNiHD3wCBP0Fqp .icon-shape .label{text-align:center;}#mermaid-svg-y7dNiHD3wCBP0Fqp .node.clickable{cursor:pointer;}#mermaid-svg-y7dNiHD3wCBP0Fqp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .arrowheadPath{fill:#333333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-y7dNiHD3wCBP0Fqp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y7dNiHD3wCBP0Fqp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-y7dNiHD3wCBP0Fqp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y7dNiHD3wCBP0Fqp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-y7dNiHD3wCBP0Fqp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-y7dNiHD3wCBP0Fqp .cluster text{fill:#333;}#mermaid-svg-y7dNiHD3wCBP0Fqp .cluster span{color:#333;}#mermaid-svg-y7dNiHD3wCBP0Fqp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-y7dNiHD3wCBP0Fqp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-y7dNiHD3wCBP0Fqp rect.text{fill:none;stroke-width:0;}#mermaid-svg-y7dNiHD3wCBP0Fqp .icon-shape,#mermaid-svg-y7dNiHD3wCBP0Fqp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y7dNiHD3wCBP0Fqp .icon-shape p,#mermaid-svg-y7dNiHD3wCBP0Fqp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-y7dNiHD3wCBP0Fqp .icon-shape .label rect,#mermaid-svg-y7dNiHD3wCBP0Fqp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y7dNiHD3wCBP0Fqp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-y7dNiHD3wCBP0Fqp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-y7dNiHD3wCBP0Fqp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ThreadPoolExecutor
线程数量
任务队列
拒绝策略
corePoolSize
maximumPoolSize
keepAliveTime
workQueue
RejectedExecutionHandler
threadFactory
任务提交后怎么执行
线程池执行流程一定要会画。
#mermaid-svg-nwU7ZpRDnyZ3sz51{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .error-icon{fill:#552222;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .marker.cross{stroke:#333333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 p{margin:0;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .cluster-label text{fill:#333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .cluster-label span{color:#333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .cluster-label span p{background-color:transparent;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .label text,#mermaid-svg-nwU7ZpRDnyZ3sz51 span{fill:#333;color:#333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .node rect,#mermaid-svg-nwU7ZpRDnyZ3sz51 .node circle,#mermaid-svg-nwU7ZpRDnyZ3sz51 .node ellipse,#mermaid-svg-nwU7ZpRDnyZ3sz51 .node polygon,#mermaid-svg-nwU7ZpRDnyZ3sz51 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .rough-node .label text,#mermaid-svg-nwU7ZpRDnyZ3sz51 .node .label text,#mermaid-svg-nwU7ZpRDnyZ3sz51 .image-shape .label,#mermaid-svg-nwU7ZpRDnyZ3sz51 .icon-shape .label{text-anchor:middle;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .rough-node .label,#mermaid-svg-nwU7ZpRDnyZ3sz51 .node .label,#mermaid-svg-nwU7ZpRDnyZ3sz51 .image-shape .label,#mermaid-svg-nwU7ZpRDnyZ3sz51 .icon-shape .label{text-align:center;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .node.clickable{cursor:pointer;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .arrowheadPath{fill:#333333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nwU7ZpRDnyZ3sz51 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nwU7ZpRDnyZ3sz51 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nwU7ZpRDnyZ3sz51 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .cluster text{fill:#333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .cluster span{color:#333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nwU7ZpRDnyZ3sz51 rect.text{fill:none;stroke-width:0;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .icon-shape,#mermaid-svg-nwU7ZpRDnyZ3sz51 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .icon-shape p,#mermaid-svg-nwU7ZpRDnyZ3sz51 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .icon-shape .label rect,#mermaid-svg-nwU7ZpRDnyZ3sz51 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nwU7ZpRDnyZ3sz51 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nwU7ZpRDnyZ3sz51 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nwU7ZpRDnyZ3sz51 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
否
是
是
否
有
无
提交任务
核心线程数是否已满
创建核心线程执行任务
阻塞队列是否已满
任务进入队列等待
线程数是否小于 maximumPoolSize
创建救急线程执行任务
执行拒绝策略
任务执行完成
队列中是否有任务
继续取队列任务执行
救急线程空闲超时后回收
用一句话背:
先用核心线程,核心线程满了进队列,队列满了再创建救急线程,线程也到最大值后触发拒绝策略。
很多人会误以为线程池会先创建到最大线程数,再放队列。默认 ThreadPoolExecutor 不是这么走的。
拒绝策略有哪些
JDK 提供了四种常见拒绝策略:
| 策略 | 行为 |
|---|---|
AbortPolicy |
直接抛异常,默认策略 |
CallerRunsPolicy |
由提交任务的线程自己执行 |
DiscardOldestPolicy |
丢弃队列中最早的任务,再尝试提交当前任务 |
DiscardPolicy |
直接丢弃当前任务,不抛异常 |
#mermaid-svg-n2y8VYLML1kzezqO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-n2y8VYLML1kzezqO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-n2y8VYLML1kzezqO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-n2y8VYLML1kzezqO .error-icon{fill:#552222;}#mermaid-svg-n2y8VYLML1kzezqO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-n2y8VYLML1kzezqO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-n2y8VYLML1kzezqO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-n2y8VYLML1kzezqO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-n2y8VYLML1kzezqO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-n2y8VYLML1kzezqO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-n2y8VYLML1kzezqO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-n2y8VYLML1kzezqO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-n2y8VYLML1kzezqO .marker.cross{stroke:#333333;}#mermaid-svg-n2y8VYLML1kzezqO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-n2y8VYLML1kzezqO p{margin:0;}#mermaid-svg-n2y8VYLML1kzezqO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-n2y8VYLML1kzezqO .cluster-label text{fill:#333;}#mermaid-svg-n2y8VYLML1kzezqO .cluster-label span{color:#333;}#mermaid-svg-n2y8VYLML1kzezqO .cluster-label span p{background-color:transparent;}#mermaid-svg-n2y8VYLML1kzezqO .label text,#mermaid-svg-n2y8VYLML1kzezqO span{fill:#333;color:#333;}#mermaid-svg-n2y8VYLML1kzezqO .node rect,#mermaid-svg-n2y8VYLML1kzezqO .node circle,#mermaid-svg-n2y8VYLML1kzezqO .node ellipse,#mermaid-svg-n2y8VYLML1kzezqO .node polygon,#mermaid-svg-n2y8VYLML1kzezqO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-n2y8VYLML1kzezqO .rough-node .label text,#mermaid-svg-n2y8VYLML1kzezqO .node .label text,#mermaid-svg-n2y8VYLML1kzezqO .image-shape .label,#mermaid-svg-n2y8VYLML1kzezqO .icon-shape .label{text-anchor:middle;}#mermaid-svg-n2y8VYLML1kzezqO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-n2y8VYLML1kzezqO .rough-node .label,#mermaid-svg-n2y8VYLML1kzezqO .node .label,#mermaid-svg-n2y8VYLML1kzezqO .image-shape .label,#mermaid-svg-n2y8VYLML1kzezqO .icon-shape .label{text-align:center;}#mermaid-svg-n2y8VYLML1kzezqO .node.clickable{cursor:pointer;}#mermaid-svg-n2y8VYLML1kzezqO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-n2y8VYLML1kzezqO .arrowheadPath{fill:#333333;}#mermaid-svg-n2y8VYLML1kzezqO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-n2y8VYLML1kzezqO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-n2y8VYLML1kzezqO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n2y8VYLML1kzezqO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-n2y8VYLML1kzezqO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n2y8VYLML1kzezqO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-n2y8VYLML1kzezqO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-n2y8VYLML1kzezqO .cluster text{fill:#333;}#mermaid-svg-n2y8VYLML1kzezqO .cluster span{color:#333;}#mermaid-svg-n2y8VYLML1kzezqO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-n2y8VYLML1kzezqO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-n2y8VYLML1kzezqO rect.text{fill:none;stroke-width:0;}#mermaid-svg-n2y8VYLML1kzezqO .icon-shape,#mermaid-svg-n2y8VYLML1kzezqO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n2y8VYLML1kzezqO .icon-shape p,#mermaid-svg-n2y8VYLML1kzezqO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-n2y8VYLML1kzezqO .icon-shape .label rect,#mermaid-svg-n2y8VYLML1kzezqO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n2y8VYLML1kzezqO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-n2y8VYLML1kzezqO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-n2y8VYLML1kzezqO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 线程池和队列都满了
拒绝策略
AbortPolicy
抛异常
CallerRunsPolicy
调用者线程执行
DiscardOldestPolicy
丢弃最老任务
DiscardPolicy
静默丢弃当前任务
业务里最怕静默丢任务。除非你非常确定任务可丢,否则不要随便用 DiscardPolicy。
常见阻塞队列
workQueue 决定任务怎么排队,也会影响线程池行为。
| 队列 | 特点 | 常见场景 |
|---|---|---|
ArrayBlockingQueue |
数组结构,有界,FIFO | 固定容量、需要明确背压 |
LinkedBlockingQueue |
链表结构,可有界,默认容量很大 | 固定线程池常见,但要小心容量 |
SynchronousQueue |
不存储元素,提交和消费必须配对 | newCachedThreadPool |
DelayedWorkQueue |
按延迟时间排序 | 定时任务线程池 |
ArrayBlockingQueue 和 LinkedBlockingQueue 的区别也常被问:
| 对比点 | ArrayBlockingQueue | LinkedBlockingQueue |
|---|---|---|
| 底层 | 数组 | 链表 |
| 容量 | 必须指定容量 | 可指定容量,默认很大 |
| 节点创建 | 初始化数组 | 入队时创建节点 |
| 锁 | 通常一把锁 | 读写可用不同锁 |
这里最关键的工程提醒是:队列一定要有容量意识。无界队列不是没有代价,只是把问题推迟到内存爆掉。
Executors 创建的四类线程池
Executors 提供了几个快捷方法:
| 方法 | 底层特点 |
|---|---|
newFixedThreadPool |
核心线程数 = 最大线程数,使用 LinkedBlockingQueue |
newSingleThreadExecutor |
单线程,使用 LinkedBlockingQueue |
newCachedThreadPool |
核心线程数 0,最大线程数 Integer.MAX_VALUE,使用 SynchronousQueue |
newScheduledThreadPool |
支持延迟和周期任务,使用 DelayedWorkQueue |
它们方便,但不建议在生产里直接用。
为什么不建议用 Executors
《Java 开发手册》里明确建议,线程池不允许使用 Executors 创建,而要通过 ThreadPoolExecutor 显式创建。
原因就是快捷方法隐藏了关键参数。
典型风险:
newFixedThreadPool和newSingleThreadExecutor使用的LinkedBlockingQueue容量很大,任务堆积可能导致 OOM。newCachedThreadPool最大线程数是Integer.MAX_VALUE,极端情况下可能创建大量线程,把机器打爆。- 默认线程名不利于排查问题。
- 拒绝策略和队列容量不明显,出了问题不好定位。
#mermaid-svg-Vkyib5mwcOIODM3v{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Vkyib5mwcOIODM3v .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Vkyib5mwcOIODM3v .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Vkyib5mwcOIODM3v .error-icon{fill:#552222;}#mermaid-svg-Vkyib5mwcOIODM3v .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Vkyib5mwcOIODM3v .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Vkyib5mwcOIODM3v .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Vkyib5mwcOIODM3v .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Vkyib5mwcOIODM3v .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Vkyib5mwcOIODM3v .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Vkyib5mwcOIODM3v .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Vkyib5mwcOIODM3v .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Vkyib5mwcOIODM3v .marker.cross{stroke:#333333;}#mermaid-svg-Vkyib5mwcOIODM3v svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Vkyib5mwcOIODM3v p{margin:0;}#mermaid-svg-Vkyib5mwcOIODM3v .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Vkyib5mwcOIODM3v .cluster-label text{fill:#333;}#mermaid-svg-Vkyib5mwcOIODM3v .cluster-label span{color:#333;}#mermaid-svg-Vkyib5mwcOIODM3v .cluster-label span p{background-color:transparent;}#mermaid-svg-Vkyib5mwcOIODM3v .label text,#mermaid-svg-Vkyib5mwcOIODM3v span{fill:#333;color:#333;}#mermaid-svg-Vkyib5mwcOIODM3v .node rect,#mermaid-svg-Vkyib5mwcOIODM3v .node circle,#mermaid-svg-Vkyib5mwcOIODM3v .node ellipse,#mermaid-svg-Vkyib5mwcOIODM3v .node polygon,#mermaid-svg-Vkyib5mwcOIODM3v .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Vkyib5mwcOIODM3v .rough-node .label text,#mermaid-svg-Vkyib5mwcOIODM3v .node .label text,#mermaid-svg-Vkyib5mwcOIODM3v .image-shape .label,#mermaid-svg-Vkyib5mwcOIODM3v .icon-shape .label{text-anchor:middle;}#mermaid-svg-Vkyib5mwcOIODM3v .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Vkyib5mwcOIODM3v .rough-node .label,#mermaid-svg-Vkyib5mwcOIODM3v .node .label,#mermaid-svg-Vkyib5mwcOIODM3v .image-shape .label,#mermaid-svg-Vkyib5mwcOIODM3v .icon-shape .label{text-align:center;}#mermaid-svg-Vkyib5mwcOIODM3v .node.clickable{cursor:pointer;}#mermaid-svg-Vkyib5mwcOIODM3v .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Vkyib5mwcOIODM3v .arrowheadPath{fill:#333333;}#mermaid-svg-Vkyib5mwcOIODM3v .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Vkyib5mwcOIODM3v .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Vkyib5mwcOIODM3v .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vkyib5mwcOIODM3v .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Vkyib5mwcOIODM3v .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vkyib5mwcOIODM3v .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Vkyib5mwcOIODM3v .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Vkyib5mwcOIODM3v .cluster text{fill:#333;}#mermaid-svg-Vkyib5mwcOIODM3v .cluster span{color:#333;}#mermaid-svg-Vkyib5mwcOIODM3v div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Vkyib5mwcOIODM3v .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Vkyib5mwcOIODM3v rect.text{fill:none;stroke-width:0;}#mermaid-svg-Vkyib5mwcOIODM3v .icon-shape,#mermaid-svg-Vkyib5mwcOIODM3v .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vkyib5mwcOIODM3v .icon-shape p,#mermaid-svg-Vkyib5mwcOIODM3v .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Vkyib5mwcOIODM3v .icon-shape .label rect,#mermaid-svg-Vkyib5mwcOIODM3v .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vkyib5mwcOIODM3v .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Vkyib5mwcOIODM3v .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Vkyib5mwcOIODM3v :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Executors 快捷创建
隐藏关键参数
队列可能过大
最大线程数可能过大
线程名不可控
拒绝策略不清晰
OOM 风险
线程耗尽 / 上下文切换严重
更推荐显式写:
java
AtomicInteger index = new AtomicInteger(1);
ThreadPoolExecutor pool = new ThreadPoolExecutor(
8,
16,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1000),
r -> new Thread(r, "order-worker-" + index.getAndIncrement()),
new ThreadPoolExecutor.CallerRunsPolicy()
);
这样至少线程数、队列容量、线程名、拒绝策略都摆在明面上。
核心线程数怎么设置
这个问题没有一条公式能包治百病,但面试里可以按任务类型说。
CPU 密集型任务,比如加密、压缩、图片处理、复杂计算,线程数通常接近 CPU 核数,常见经验值是 N + 1。
IO 密集型任务,比如数据库、文件、网络请求,线程会大量等待 IO,可以适当多一些,比如 2N + 1,或者根据等待时间和计算时间估算。
java
int processors = Runtime.getRuntime().availableProcessors();
System.out.println(processors);
但更工程化的回答是:
线程数不是拍脑袋一次定死,要结合任务耗时、吞吐、队列长度、CPU 使用率、响应时间和拒绝次数持续压测调整。
#mermaid-svg-VsEgN3tPaiD6oqqu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VsEgN3tPaiD6oqqu .error-icon{fill:#552222;}#mermaid-svg-VsEgN3tPaiD6oqqu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VsEgN3tPaiD6oqqu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VsEgN3tPaiD6oqqu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VsEgN3tPaiD6oqqu .marker.cross{stroke:#333333;}#mermaid-svg-VsEgN3tPaiD6oqqu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VsEgN3tPaiD6oqqu p{margin:0;}#mermaid-svg-VsEgN3tPaiD6oqqu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VsEgN3tPaiD6oqqu .cluster-label text{fill:#333;}#mermaid-svg-VsEgN3tPaiD6oqqu .cluster-label span{color:#333;}#mermaid-svg-VsEgN3tPaiD6oqqu .cluster-label span p{background-color:transparent;}#mermaid-svg-VsEgN3tPaiD6oqqu .label text,#mermaid-svg-VsEgN3tPaiD6oqqu span{fill:#333;color:#333;}#mermaid-svg-VsEgN3tPaiD6oqqu .node rect,#mermaid-svg-VsEgN3tPaiD6oqqu .node circle,#mermaid-svg-VsEgN3tPaiD6oqqu .node ellipse,#mermaid-svg-VsEgN3tPaiD6oqqu .node polygon,#mermaid-svg-VsEgN3tPaiD6oqqu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VsEgN3tPaiD6oqqu .rough-node .label text,#mermaid-svg-VsEgN3tPaiD6oqqu .node .label text,#mermaid-svg-VsEgN3tPaiD6oqqu .image-shape .label,#mermaid-svg-VsEgN3tPaiD6oqqu .icon-shape .label{text-anchor:middle;}#mermaid-svg-VsEgN3tPaiD6oqqu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VsEgN3tPaiD6oqqu .rough-node .label,#mermaid-svg-VsEgN3tPaiD6oqqu .node .label,#mermaid-svg-VsEgN3tPaiD6oqqu .image-shape .label,#mermaid-svg-VsEgN3tPaiD6oqqu .icon-shape .label{text-align:center;}#mermaid-svg-VsEgN3tPaiD6oqqu .node.clickable{cursor:pointer;}#mermaid-svg-VsEgN3tPaiD6oqqu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VsEgN3tPaiD6oqqu .arrowheadPath{fill:#333333;}#mermaid-svg-VsEgN3tPaiD6oqqu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VsEgN3tPaiD6oqqu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VsEgN3tPaiD6oqqu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VsEgN3tPaiD6oqqu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VsEgN3tPaiD6oqqu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VsEgN3tPaiD6oqqu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VsEgN3tPaiD6oqqu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VsEgN3tPaiD6oqqu .cluster text{fill:#333;}#mermaid-svg-VsEgN3tPaiD6oqqu .cluster span{color:#333;}#mermaid-svg-VsEgN3tPaiD6oqqu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VsEgN3tPaiD6oqqu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VsEgN3tPaiD6oqqu rect.text{fill:none;stroke-width:0;}#mermaid-svg-VsEgN3tPaiD6oqqu .icon-shape,#mermaid-svg-VsEgN3tPaiD6oqqu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VsEgN3tPaiD6oqqu .icon-shape p,#mermaid-svg-VsEgN3tPaiD6oqqu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VsEgN3tPaiD6oqqu .icon-shape .label rect,#mermaid-svg-VsEgN3tPaiD6oqqu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VsEgN3tPaiD6oqqu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VsEgN3tPaiD6oqqu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VsEgN3tPaiD6oqqu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} CPU 密集
IO 密集
确定线程数
任务类型
接近 CPU 核数
可大于 CPU 核数
压测观察 CPU / RT / 队列
调整 corePoolSize / queue / maxPoolSize
面试怎么答
可以这样回答:
线程池核心参数有七个:核心线程数、最大线程数、救急线程存活时间、时间单位、阻塞队列、线程工厂、拒绝策略。
任务提交后,先判断核心线程是否已满,没满就创建核心线程执行;核心线程满了就尝试进入阻塞队列;队列也满了,再看是否能创建救急线程;如果线程数已经达到最大值,就触发拒绝策略。
常见队列有 ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、DelayedWorkQueue。常见拒绝策略有抛异常、调用者执行、丢弃最老任务、直接丢弃。
不建议直接用 Executors,因为它会隐藏队列容量和最大线程数等关键参数,可能导致任务堆积 OOM 或线程数过多。生产里更推荐手动创建 ThreadPoolExecutor,明确线程名、队列容量和拒绝策略。