forked from itwanger/toBeBetterJavaer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpool.html
More file actions
342 lines (323 loc) · 116 KB
/
Copy pathpool.html
File metadata and controls
342 lines (323 loc) · 116 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="generator" content="VuePress 2.0.0-beta.46" />
<meta name="theme" content="VuePress Theme Hope" />
<meta property="og:url" content="https://tobebetterjavaer.com/thread/pool.html"><meta property="og:site_name" content="Java 程序员进阶之路"><meta property="og:title" content="面试必备:Java线程池解析"><meta property="og:type" content="article"><meta property="og:updated_time" content="2022-05-12T08:24:21.000Z"><meta property="og:locale" content="zh-CN"><meta property="article:tag" content="Java"><meta property="article:modified_time" content="2022-05-12T08:24:21.000Z"><script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5230ac143650bf5eb3c14f3fb9b1d3ec";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script><link rel="stylesheet" href="//at.alicdn.com/t/font_3180624_7cy10l7jqqh.css"><link rel="icon" href="/favicon.ico"><link rel="icon" href="/assets/icon/chrome-mask-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-mask-192.png" type="image/png" sizes="192x192"><link rel="icon" href="/assets/icon/chrome-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-192.png" type="image/png" sizes="192x192"><link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials"><meta name="theme-color" content="#46bd87"><link rel="apple-touch-icon" href="/assets/icon/apple-icon-152.png"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="msapplication-TileImage" content="/assets/icon/ms-icon-144.png"><meta name="msapplication-TileColor" content="#ffffff"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"><title>面试必备:Java线程池解析 | Java 程序员进阶之路</title><meta name="description" content="一份通俗易懂、风趣幽默的Java学习指南,内容涵盖Java基础、Java并发编程、Java虚拟机、Java企业级开发、Java面试等核心知识点。学Java,就认准Java程序员进阶之路">
<style>
:root {
--bg-color: #fff;
}
html[data-theme="dark"] {
--bg-color: #1d2025;
}
html,
body {
background-color: var(--bg-color);
}
</style>
<script>
const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
const systemDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
document.querySelector("html").setAttribute("data-theme", "dark");
}
</script>
<link rel="stylesheet" href="/assets/style.c081fa20.css">
<link rel="modulepreload" href="/assets/app.41bad062.js"><link rel="modulepreload" href="/assets/pool.html.95b51514.js"><link rel="modulepreload" href="/assets/plugin-vue_export-helper.21dcd24c.js"><link rel="modulepreload" href="/assets/pool.html.1918e02b.js">
</head>
<body>
<div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">Skip to content</a><!--]--><div class="theme-container has-toc"><!--[--><!--[--><header class="navbar"><div class="navbar-left"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!----><a href="/" class="brand"><img class="logo" src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/logo-02.png" alt="Java 程序员进阶之路"><!----><span class="site-name hide-in-pad">Java 程序员进阶之路</span></a><!----></div><div class="navbar-center"><!----><nav class="nav-links"><div class="nav-item hide-in-mobile"><a href="/blog.html" class="nav-link" aria-label="博客"><span class="icon iconfont icon-gaishu" style=""></span>博客<!----></a></div><div class="nav-item hide-in-mobile"><a href="/home.html" class="nav-link" aria-label="进阶之路"><span class="icon iconfont icon-lujing" style=""></span>进阶之路<!----></a></div><div class="nav-item hide-in-mobile"><a href="/zhishixingqiu/" class="nav-link" aria-label="知识星球"><span class="icon iconfont icon-Artboard" style=""></span>知识星球<!----></a></div><div class="nav-item hide-in-mobile"><a href="/xuexiluxian/" class="nav-link" aria-label="学习路线"><span class="icon iconfont icon-luxian" style=""></span>学习路线<!----></a></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="珍藏资源"><span class="title"><span class="icon iconfont icon-youzhi" style=""></span>珍藏资源</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/download/java.html" class="nav-link" aria-label="电子书下载"><span class="icon iconfont icon-java" style=""></span>电子书下载<!----></a></li><li class="dropdown-item"><a href="/sidebar/sanfene/nixi.html" class="nav-link" aria-label="面渣逆袭"><span class="icon iconfont icon-zhunbei" style=""></span>面渣逆袭<!----></a></li><li class="dropdown-item"><a href="/download/nicearticle.html" class="nav-link" aria-label="优质文章"><span class="icon iconfont icon-youzhi" style=""></span>优质文章<!----></a></li><li class="dropdown-item"><a href="/download/history.html" class="nav-link" aria-label="网络日志"><span class="icon iconfont icon-rizhi" style=""></span>网络日志<!----></a></li><li class="dropdown-item"><a href="/nice-article/itmind/" class="nav-link" aria-label="破解合集"><span class="icon iconfont icon-zhongyaotishi" style=""></span>破解合集<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><a href="https://space.bilibili.com/513340480" rel="noopener noreferrer" target="_blank" aria-label="B站视频" class="nav-link"><span class="icon iconfont icon-bzhan" style=""></span>B站视频<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div></nav><!----></div><div class="navbar-right"><!----><div class="nav-item"><!----></div><div class="nav-item"><a class="repo-link" href="https://github.com/itwanger/toBeBetterJavaer" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" class="icon github-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="github icon" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><path d="M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"></path></svg></a></div><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:block;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:none;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><div id="docsearch-container"></div><!----><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow left"></span></div><aside class="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><!--[--><a href="/home.html" class="nav-link sidebar-link sidebar-page" aria-label="一、前言"><!---->一、前言<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">二、Java核心</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.1 Java概述</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.2 Java语法基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.3 数组&字符串</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.4 面向对象编程</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.5 集合框架(容器)</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.6 IO</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.7 异常处理</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.8 常用工具类</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.9 Java新特性</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.10 Java重要知识点</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">2.11 并发编程</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/thread/wangzhe-thread.html" class="nav-link sidebar-link sidebar-page" aria-label="创建Java线程的3种方式"><!---->创建Java线程的3种方式<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/thread-state-and-method.html" class="nav-link sidebar-link sidebar-page" aria-label="线程的6种状态及切换"><!---->线程的6种状态及切换<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/thread-group-and-thread-priority.html" class="nav-link sidebar-link sidebar-page" aria-label="线程组和线程优先级"><!---->线程组和线程优先级<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/why-need-thread.html" class="nav-link sidebar-link sidebar-page" aria-label="进程与线程的区别"><!---->进程与线程的区别<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/thread-bring-some-problem.html" class="nav-link sidebar-link sidebar-page" aria-label="并发编程带来了哪些问题"><!---->并发编程带来了哪些问题<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/jmm.html" class="nav-link sidebar-link sidebar-page" aria-label="Java内存模型"><!---->Java内存模型<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/volatile.html" class="nav-link sidebar-link sidebar-page" aria-label="volatile"><!---->volatile<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/synchronized.html" class="nav-link sidebar-link sidebar-page" aria-label="synchronized"><!---->synchronized<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/cas.html" class="nav-link sidebar-link sidebar-page" aria-label="CAS的原理"><!---->CAS的原理<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/aqs.html" class="nav-link sidebar-link sidebar-page" aria-label="AQS详解"><!---->AQS详解<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/lock.html" class="nav-link sidebar-link sidebar-page" aria-label="锁"><!---->锁<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/reentrantLock.html" class="nav-link sidebar-link sidebar-page" aria-label="重入锁ReentrantLock"><!---->重入锁ReentrantLock<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ReentrantReadWriteLock.html" class="nav-link sidebar-link sidebar-page" aria-label="读写锁ReentrantReadWriteLock"><!---->读写锁ReentrantReadWriteLock<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/condition.html" class="nav-link sidebar-link sidebar-page" aria-label="线程协作类Condition"><!---->线程协作类Condition<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/LockSupport.html" class="nav-link sidebar-link sidebar-page" aria-label="线程阻塞唤醒类LockSupport"><!---->线程阻塞唤醒类LockSupport<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/map.html" class="nav-link sidebar-link sidebar-page" aria-label="并发集合容器"><!---->并发集合容器<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ConcurrentHashMap.html" class="nav-link sidebar-link sidebar-page" aria-label="ConcurrentHashMap"><!---->ConcurrentHashMap<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ConcurrentLinkedQueue.html" class="nav-link sidebar-link sidebar-page" aria-label="ConcurrentLinkedQueue"><!---->ConcurrentLinkedQueue<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/CopyOnWriteArrayList.html" class="nav-link sidebar-link sidebar-page" aria-label="CopyOnWriteArrayList"><!---->CopyOnWriteArrayList<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ThreadLocal.html" class="nav-link sidebar-link sidebar-page" aria-label="ThreadLocal"><!---->ThreadLocal<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/BlockingQueue.html" class="nav-link sidebar-link sidebar-page" aria-label="BlockingQueue"><!---->BlockingQueue<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a aria-current="page" href="/thread/pool.html" class="router-link-active router-link-exact-active nav-link active sidebar-link sidebar-page active" aria-label="线程池"><!---->线程池<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#为什么要使用线程池" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="为什么要使用线程池"><!---->为什么要使用线程池<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#线程池的原理" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="线程池的原理"><!---->线程池的原理<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#threadpoolexecutor提供的构造方法" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="ThreadPoolExecutor提供的构造方法"><!---->ThreadPoolExecutor提供的构造方法<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#threadpoolexecutor的策略" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="ThreadPoolExecutor的策略"><!---->ThreadPoolExecutor的策略<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#线程池主要的任务处理流程" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="线程池主要的任务处理流程"><!---->线程池主要的任务处理流程<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#threadpoolexecutor如何做到线程复用的" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="ThreadPoolExecutor如何做到线程复用的?"><!---->ThreadPoolExecutor如何做到线程复用的?<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#四种常见的线程池" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="四种常见的线程池"><!---->四种常见的线程池<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#newcachedthreadpool" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="newCachedThreadPool"><!---->newCachedThreadPool<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#newfixedthreadpool" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="newFixedThreadPool"><!---->newFixedThreadPool<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#newsinglethreadexecutor" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="newSingleThreadExecutor"><!---->newSingleThreadExecutor<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/pool.html#newscheduledthreadpool" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="newScheduledThreadPool"><!---->newScheduledThreadPool<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li></ul><!--]--></li><li><!--[--><a href="/thread/ScheduledThreadPoolExecutor.html" class="nav-link sidebar-link sidebar-page" aria-label="计划任务"><!---->计划任务<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/atomic.html" class="nav-link sidebar-link sidebar-page" aria-label="原子操作类"><!---->原子操作类<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/CountDownLatch.html" class="nav-link sidebar-link sidebar-page" aria-label="通信工具类CountDownLatch"><!---->通信工具类CountDownLatch<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/fork-join.html" class="nav-link sidebar-link sidebar-page" aria-label="Fork/Join框架"><!---->Fork/Join框架<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/shengchanzhe-xiaofeizhe.html" class="nav-link sidebar-link sidebar-page" aria-label="生产者-消费者模式"><!---->生产者-消费者模式<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.12 JVM</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">三、Java企业级开发</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">四、数据库</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">五、计算机基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">六、求职面试</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">七、学习资源</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">八、学习建议</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">九、知识库搭建</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">十、联系作者</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!--[--><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><!---->面试必备:Java线程池解析</h1><div class="page-info"><span class="author-info" aria-label="作者🖊" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon author-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="author icon"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"></path></svg><span><a class="author-item" href="/about-the-author/" target="_blank" rel="noopener noreferrer">沉默王二</a></span><span property="author" content="沉默王二"></span></span><!----><span class="date-info" aria-label="写作日期📅" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="calendar icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"></path></svg><span>2022年3月23日</span><meta property="datePublished" content="2022-03-23T12:08:58.000Z"></span><span class="category-info" aria-label="分类🌈" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon category-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="category icon"><path d="M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"></path></svg><ul class="categories-wrapper"><li class="category category0 clickable" role="navigation">Java核心</li><li class="category category6 clickable" role="navigation">并发编程</li><meta property="articleSection" content="Java核心,并发编程"></ul></span><span aria-label="标签🏷" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon tag-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="tag icon"><path d="M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"></path></svg><ul class="tags-wrapper"><li class="tag tag4 clickable" role="navigation">Java</li></ul><meta property="keywords" content="Java"></span><span class="reading-time-info" aria-label="阅读时间⌛" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>大约 15 分钟</span><meta property="timeRequired" content="PT15M"></span></div><hr></div><div class="toc-place-holder"><aside id="toc"><div class="toc-header">此页内容</div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#为什么要使用线程池" class="router-link-active router-link-exact-active toc-link level2">为什么要使用线程池</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#线程池的原理" class="router-link-active router-link-exact-active toc-link level2">线程池的原理</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#threadpoolexecutor提供的构造方法" class="router-link-active router-link-exact-active toc-link level3">ThreadPoolExecutor提供的构造方法</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#threadpoolexecutor的策略" class="router-link-active router-link-exact-active toc-link level3">ThreadPoolExecutor的策略</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#线程池主要的任务处理流程" class="router-link-active router-link-exact-active toc-link level3">线程池主要的任务处理流程</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#threadpoolexecutor如何做到线程复用的" class="router-link-active router-link-exact-active toc-link level3">ThreadPoolExecutor如何做到线程复用的?</a></li><!----><!--]--></ul><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#四种常见的线程池" class="router-link-active router-link-exact-active toc-link level2">四种常见的线程池</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#newcachedthreadpool" class="router-link-active router-link-exact-active toc-link level3">newCachedThreadPool</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#newfixedthreadpool" class="router-link-active router-link-exact-active toc-link level3">newFixedThreadPool</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#newsinglethreadexecutor" class="router-link-active router-link-exact-active toc-link level3">newSingleThreadExecutor</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/pool.html#newscheduledthreadpool" class="router-link-active router-link-exact-active toc-link level3">newScheduledThreadPool</a></li><!----><!--]--></ul><!--]--></ul></div></aside></div><!----><div class="theme-hope-content"><h2 id="为什么要使用线程池" tabindex="-1"><a class="header-anchor" href="#为什么要使用线程池" aria-hidden="true">#</a> 为什么要使用线程池</h2><p>使用线程池主要有以下三个原因:</p><ol><li>创建/销毁线程需要消耗系统资源,线程池可以<strong>复用已创建的线程</strong>。</li><li><strong>控制并发的数量</strong>。并发数量过多,可能会导致资源消耗过多,从而造成服务器崩溃。(主要原因)</li><li><strong>可以对线程做统一管理</strong>。</li></ol><h2 id="线程池的原理" tabindex="-1"><a class="header-anchor" href="#线程池的原理" aria-hidden="true">#</a> 线程池的原理</h2><p>Java中的线程池顶层接口是<code>Executor</code>接口,<code>ThreadPoolExecutor</code>是这个接口的实现类。</p><p>我们先看看<code>ThreadPoolExecutor</code>类。</p><h3 id="threadpoolexecutor提供的构造方法" tabindex="-1"><a class="header-anchor" href="#threadpoolexecutor提供的构造方法" aria-hidden="true">#</a> ThreadPoolExecutor提供的构造方法</h3><p>一共有四个构造方法:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// 五个参数的构造函数</span>
<span class="token keyword">public</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">,</span>
<span class="token keyword">int</span> maximumPoolSize<span class="token punctuation">,</span>
<span class="token keyword">long</span> keepAliveTime<span class="token punctuation">,</span>
<span class="token class-name">TimeUnit</span> unit<span class="token punctuation">,</span>
<span class="token class-name">BlockingQueue</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Runnable</span><span class="token punctuation">></span></span> workQueue<span class="token punctuation">)</span>
<span class="token comment">// 六个参数的构造函数-1</span>
<span class="token keyword">public</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">,</span>
<span class="token keyword">int</span> maximumPoolSize<span class="token punctuation">,</span>
<span class="token keyword">long</span> keepAliveTime<span class="token punctuation">,</span>
<span class="token class-name">TimeUnit</span> unit<span class="token punctuation">,</span>
<span class="token class-name">BlockingQueue</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Runnable</span><span class="token punctuation">></span></span> workQueue<span class="token punctuation">,</span>
<span class="token class-name">ThreadFactory</span> threadFactory<span class="token punctuation">)</span>
<span class="token comment">// 六个参数的构造函数-2</span>
<span class="token keyword">public</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">,</span>
<span class="token keyword">int</span> maximumPoolSize<span class="token punctuation">,</span>
<span class="token keyword">long</span> keepAliveTime<span class="token punctuation">,</span>
<span class="token class-name">TimeUnit</span> unit<span class="token punctuation">,</span>
<span class="token class-name">BlockingQueue</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Runnable</span><span class="token punctuation">></span></span> workQueue<span class="token punctuation">,</span>
<span class="token class-name">RejectedExecutionHandler</span> handler<span class="token punctuation">)</span>
<span class="token comment">// 七个参数的构造函数</span>
<span class="token keyword">public</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">,</span>
<span class="token keyword">int</span> maximumPoolSize<span class="token punctuation">,</span>
<span class="token keyword">long</span> keepAliveTime<span class="token punctuation">,</span>
<span class="token class-name">TimeUnit</span> unit<span class="token punctuation">,</span>
<span class="token class-name">BlockingQueue</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Runnable</span><span class="token punctuation">></span></span> workQueue<span class="token punctuation">,</span>
<span class="token class-name">ThreadFactory</span> threadFactory<span class="token punctuation">,</span>
<span class="token class-name">RejectedExecutionHandler</span> handler<span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>涉及到5~7个参数,我们先看看必须的5个参数是什么意思:</p><ul><li><p><strong>int corePoolSize</strong>:该线程池中<strong>核心线程数最大值</strong></p><blockquote><p>核心线程:线程池中有两类线程,核心线程和非核心线程。核心线程默认情况下会一直存在于线程池中,即使这个核心线程什么都不干(铁饭碗),而非核心线程如果长时间的闲置,就会被销毁(临时工)。</p></blockquote></li><li><p><strong>int maximumPoolSize</strong>:该线程池中<strong>线程总数最大值</strong> 。</p><blockquote><p>该值等于核心线程数量 + 非核心线程数量。</p></blockquote></li><li><p><strong>long keepAliveTime</strong>:<strong>非核心线程闲置超时时长</strong>。</p><blockquote><p>非核心线程如果处于闲置状态超过该值,就会被销毁。如果设置allowCoreThreadTimeOut(true),则会也作用于核心线程。</p></blockquote></li><li><p><strong>TimeUnit unit</strong>:keepAliveTime的单位。</p><p>TimeUnit是一个枚举类型 ,包括以下属性:</p><blockquote><p>NANOSECONDS : 1微毫秒 = 1微秒 / 1000 MICROSECONDS : 1微秒 = 1毫秒 / 1000 MILLISECONDS : 1毫秒 = 1秒 /1000 SECONDS : 秒 MINUTES : 分 HOURS : 小时 DAYS : 天</p></blockquote></li><li><p><strong>BlockingQueue workQueue</strong>:阻塞队列,维护着<strong>等待执行的Runnable任务对象</strong>。</p><p>常用的几个阻塞队列:</p><ol><li><p><strong>LinkedBlockingQueue</strong></p><p>链式阻塞队列,底层数据结构是链表,默认大小是<code>Integer.MAX_VALUE</code>,也可以指定大小。</p></li><li><p><strong>ArrayBlockingQueue</strong></p><p>数组阻塞队列,底层数据结构是数组,需要指定队列的大小。</p></li><li><p><strong>SynchronousQueue</strong></p><p>同步队列,内部容量为0,每个put操作必须等待一个take操作,反之亦然。</p></li><li><p><strong>DelayQueue</strong></p><p>延迟队列,该队列中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素 。</p></li></ol></li></ul><blockquote><p>我们将在下一章中重点介绍各种阻塞队列</p></blockquote><p>好了,介绍完5个必须的参数之后,还有两个非必须的参数。</p><ul><li><p><strong>ThreadFactory threadFactory</strong></p><p>创建线程的工厂 ,用于批量创建线程,统一在创建线程时设置一些参数,如是否守护线程、线程的优先级等。如果不指定,会新建一个默认的线程工厂。</p></li></ul><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">DefaultThreadFactory</span> <span class="token keyword">implements</span> <span class="token class-name">ThreadFactory</span> <span class="token punctuation">{</span>
<span class="token comment">// 省略属性</span>
<span class="token comment">// 构造函数</span>
<span class="token class-name">DefaultThreadFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">SecurityManager</span> s <span class="token operator">=</span> <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">getSecurityManager</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
group <span class="token operator">=</span> <span class="token punctuation">(</span>s <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token operator">?</span> s<span class="token punctuation">.</span><span class="token function">getThreadGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span>
<span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getThreadGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
namePrefix <span class="token operator">=</span> <span class="token string">"pool-"</span> <span class="token operator">+</span>
poolNumber<span class="token punctuation">.</span><span class="token function">getAndIncrement</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span>
<span class="token string">"-thread-"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 省略</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul><li><p><strong>RejectedExecutionHandler handler</strong></p><p><strong>拒绝处理策略</strong>,线程数量大于最大线程数就会采用拒绝处理策略,四种拒绝处理的策略为 :</p><ol><li><p><strong>ThreadPoolExecutor.AbortPolicy</strong>:<strong>默认拒绝处理策略</strong>,丢弃任务并抛出RejectedExecutionException异常。</p></li><li><p><strong>ThreadPoolExecutor.DiscardPolicy</strong>:丢弃新来的任务,但是不抛出异常。</p></li><li><p><strong>ThreadPoolExecutor.DiscardOldestPolicy</strong>:丢弃队列头部(最旧的)的任务,然后重新尝试执行程序(如果再次失败,重复此过程)。</p></li><li><p><strong>ThreadPoolExecutor.CallerRunsPolicy</strong>:由调用线程处理该任务。</p></li></ol></li></ul><h3 id="threadpoolexecutor的策略" tabindex="-1"><a class="header-anchor" href="#threadpoolexecutor的策略" aria-hidden="true">#</a> ThreadPoolExecutor的策略</h3><p>线程池本身有一个调度线程,这个线程就是用于管理布控整个线程池里的各种任务和事务,例如创建线程、销毁线程、任务队列管理、线程队列管理等等。</p><p>故线程池也有自己的状态。<code>ThreadPoolExecutor</code>类中使用了一些<code>final int</code>常量变量来表示线程池的状态 ,分别为RUNNING、SHUTDOWN、STOP、TIDYING 、TERMINATED。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// runState is stored in the high-order bits</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> RUNNING <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span> <span class="token operator"><<</span> COUNT_BITS<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> SHUTDOWN <span class="token operator">=</span> <span class="token number">0</span> <span class="token operator"><<</span> COUNT_BITS<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> STOP <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator"><<</span> COUNT_BITS<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> TIDYING <span class="token operator">=</span> <span class="token number">2</span> <span class="token operator"><<</span> COUNT_BITS<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> TERMINATED <span class="token operator">=</span> <span class="token number">3</span> <span class="token operator"><<</span> COUNT_BITS<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul><li><p>线程池创建后处于<strong>RUNNING</strong>状态。</p></li><li><p>调用shutdown()方法后处于<strong>SHUTDOWN</strong>状态,线程池不能接受新的任务,清除一些空闲worker,不会等待阻塞队列的任务完成。</p></li><li><p>调用shutdownNow()方法后处于<strong>STOP</strong>状态,线程池不能接受新的任务,中断所有线程,阻塞队列中没有被执行的任务全部丢弃。此时,poolsize=0,阻塞队列的size也为0。</p></li><li><p>当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为<strong>TIDYING</strong>状态。接着会执行terminated()函数。</p><blockquote><p>ThreadPoolExecutor中有一个控制状态的属性叫<code>ctl</code>,它是一个AtomicInteger类型的变量。线程池状态就是通过AtomicInteger类型的成员变量<code>ctl</code>来获取的。</p><p>获取的<code>ctl</code>值传入<code>runStateOf</code>方法,与<code>~CAPACITY</code>位与运算(<code>CAPACITY</code>是低29位全1的int变量)。</p><p><code>~CAPACITY</code>在这里相当于掩码,用来获取ctl的高3位,表示线程池状态;而另外的低29位用于表示工作线程数</p></blockquote></li><li><p>线程池处在TIDYING状态时,<strong>执行完terminated()方法之后</strong>,就会由 <strong>TIDYING -> TERMINATED</strong>, 线程池被设置为TERMINATED状态。</p></li></ul><h3 id="线程池主要的任务处理流程" tabindex="-1"><a class="header-anchor" href="#线程池主要的任务处理流程" aria-hidden="true">#</a> 线程池主要的任务处理流程</h3><p>处理任务的核心方法是<code>execute</code>,我们看看 JDK 1.8 源码中<code>ThreadPoolExecutor</code>是如何处理线程任务的:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// JDK 1.8 </span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">execute</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> command<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>command <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NullPointerException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 1.当前线程数小于corePoolSize,则调用addWorker创建核心线程执行任务</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">workerCountOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator"><</span> corePoolSize<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">addWorker</span><span class="token punctuation">(</span>command<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 2.如果不小于corePoolSize,则将任务添加到workQueue队列。</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isRunning</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">&&</span> workQueue<span class="token punctuation">.</span><span class="token function">offer</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> recheck <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2.1 如果isRunning返回false(状态检查),则remove这个任务,然后执行拒绝策略。</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span> <span class="token function">isRunning</span><span class="token punctuation">(</span>recheck<span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token function">remove</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">reject</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2.2 线程池处于running状态,但是没有线程,则创建线程</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">workerCountOf</span><span class="token punctuation">(</span>recheck<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token function">addWorker</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 3.如果放入workQueue失败,则创建非核心线程执行任务,</span>
<span class="token comment">// 如果这时创建非核心线程失败(当前线程总数不小于maximumPoolSize时),就会执行拒绝策略。</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">addWorker</span><span class="token punctuation">(</span>command<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token function">reject</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>ctl.get()</code>是获取线程池状态,用<code>int</code>类型表示。第二步中,入队前进行了一次<code>isRunning</code>判断,入队之后,又进行了一次<code>isRunning</code>判断。</p><p><strong>为什么要二次检查线程池的状态?</strong></p><p>在多线程的环境下,线程池的状态是时刻发生变化的。很有可能刚获取线程池状态后线程池状态就改变了。判断是否将<code>command</code>加入<code>workqueue</code>是线程池之前的状态。倘若没有二次检查,万一线程池处于非<strong>RUNNING</strong>状态(在多线程环境下很有可能发生),那么<code>command</code>永远不会执行。</p><p><strong>总结一下处理流程</strong></p><ol><li>线程总数量 < corePoolSize,无论线程是否空闲,都会新建一个核心线程执行任务(让核心线程数量快速达到corePoolSize,在核心线程数量 < corePoolSize时)。<strong>注意,这一步需要获得全局锁。</strong></li><li>线程总数量 >= corePoolSize时,新来的线程任务会进入任务队列中等待,然后空闲的核心线程会依次去缓存队列中取任务来执行(体现了<strong>线程复用</strong>)。</li><li>当缓存队列满了,说明这个时候任务已经多到爆棚,需要一些“临时工”来执行这些任务了。于是会创建非核心线程去执行这个任务。<strong>注意,这一步需要获得全局锁。</strong></li><li>缓存队列满了, 且总线程数达到了maximumPoolSize,则会采取上面提到的拒绝策略进行处理。</li></ol><p>整个过程如图所示:</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/thread/pool-f9e419fa-9d42-44fc-b14e-5b618a6f906d.png" alt=""></p><h3 id="threadpoolexecutor如何做到线程复用的" tabindex="-1"><a class="header-anchor" href="#threadpoolexecutor如何做到线程复用的" aria-hidden="true">#</a> ThreadPoolExecutor如何做到线程复用的?</h3><p>我们知道,一个线程在创建的时候会指定一个线程任务,当执行完这个线程任务之后,线程自动销毁。但是线程池却可以复用线程,即一个线程执行完线程任务后不销毁,继续执行另外的线程任务。<strong>那么,线程池如何做到线程复用呢?</strong></p><p>原来,ThreadPoolExecutor在创建线程时,会将线程封装成<strong>工作线程worker</strong>,并放入<strong>工作线程组</strong>中,然后这个worker反复从阻塞队列中拿任务去执行。话不多说,我们继续看看源码(一定要仔细看,前后有联系)</p><p>这里的<code>addWorker</code>方法是在上面提到的<code>execute</code>方法里面调用的,先看看上半部分:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// ThreadPoolExecutor.addWorker方法源码上半部分</span>
<span class="token keyword">private</span> <span class="token keyword">boolean</span> <span class="token function">addWorker</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> firstTask<span class="token punctuation">,</span> <span class="token keyword">boolean</span> core<span class="token punctuation">)</span> <span class="token punctuation">{</span>
retry<span class="token operator">:</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> rs <span class="token operator">=</span> <span class="token function">runStateOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Check if queue empty only if necessary.</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>rs <span class="token operator">>=</span> SHUTDOWN <span class="token operator">&&</span>
<span class="token operator">!</span> <span class="token punctuation">(</span>rs <span class="token operator">==</span> SHUTDOWN <span class="token operator">&&</span>
firstTask <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&&</span>
<span class="token operator">!</span> workQueue<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> wc <span class="token operator">=</span> <span class="token function">workerCountOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>wc <span class="token operator">>=</span> CAPACITY <span class="token operator">||</span>
<span class="token comment">// 1.如果core是ture,证明需要创建的线程为核心线程,则先判断当前线程是否大于核心线程</span>
<span class="token comment">// 如果core是false,证明需要创建的是非核心线程,则先判断当前线程数是否大于总线程数</span>
<span class="token comment">// 如果不小于,则返回false</span>
wc <span class="token operator">>=</span> <span class="token punctuation">(</span>core <span class="token operator">?</span> corePoolSize <span class="token operator">:</span> maximumPoolSize<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">compareAndIncrementWorkerCount</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">break</span> retry<span class="token punctuation">;</span>
c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Re-read ctl</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">runStateOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">!=</span> rs<span class="token punctuation">)</span>
<span class="token keyword">continue</span> retry<span class="token punctuation">;</span>
<span class="token comment">// else CAS failed due to workerCount change; retry inner loop</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>上半部分主要是判断线程数量是否超出阈值,超过了就返回false。我们继续看下半部分:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code> <span class="token comment">// ThreadPoolExecutor.addWorker方法源码下半部分</span>
<span class="token keyword">boolean</span> workerStarted <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">boolean</span> workerAdded <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token class-name">Worker</span> w <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 1.创建一个worker对象</span>
w <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Worker</span><span class="token punctuation">(</span>firstTask<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2.实例化一个Thread对象</span>
<span class="token keyword">final</span> <span class="token class-name">Thread</span> t <span class="token operator">=</span> w<span class="token punctuation">.</span>thread<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>t <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 3.线程池全局锁</span>
<span class="token keyword">final</span> <span class="token class-name">ReentrantLock</span> mainLock <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mainLock<span class="token punctuation">;</span>
mainLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// Recheck while holding lock.</span>
<span class="token comment">// Back out on ThreadFactory failure or if</span>
<span class="token comment">// shut down before lock acquired.</span>
<span class="token keyword">int</span> rs <span class="token operator">=</span> <span class="token function">runStateOf</span><span class="token punctuation">(</span>ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>rs <span class="token operator"><</span> SHUTDOWN <span class="token operator">||</span>
<span class="token punctuation">(</span>rs <span class="token operator">==</span> SHUTDOWN <span class="token operator">&&</span> firstTask <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>t<span class="token punctuation">.</span><span class="token function">isAlive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// precheck that t is startable</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalThreadStateException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
workers<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> s <span class="token operator">=</span> workers<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>s <span class="token operator">></span> largestPoolSize<span class="token punctuation">)</span>
largestPoolSize <span class="token operator">=</span> s<span class="token punctuation">;</span>
workerAdded <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
mainLock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>workerAdded<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 4.启动这个线程</span>
t<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
workerStarted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span> workerStarted<span class="token punctuation">)</span>
<span class="token function">addWorkerFailed</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> workerStarted<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>创建<code>worker</code>对象,并初始化一个<code>Thread</code>对象,然后启动这个线程对象。</p><p>我们接着看看<code>Worker</code>类,仅展示部分源码:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// Worker类部分源码</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">Worker</span> <span class="token keyword">extends</span> <span class="token class-name">AbstractQueuedSynchronizer</span> <span class="token keyword">implements</span> <span class="token class-name">Runnable</span><span class="token punctuation">{</span>
<span class="token keyword">final</span> <span class="token class-name">Thread</span> thread<span class="token punctuation">;</span>
<span class="token class-name">Runnable</span> firstTask<span class="token punctuation">;</span>
<span class="token class-name">Worker</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> firstTask<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setState</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// inhibit interrupts until runWorker</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>firstTask <span class="token operator">=</span> firstTask<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>thread <span class="token operator">=</span> <span class="token function">getThreadFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">newThread</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">runWorker</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//其余代码略...</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>Worker</code>类实现了<code>Runnable</code>接口,所以<code>Worker</code>也是一个线程任务。在构造方法中,创建了一个线程,线程的任务就是自己。故<code>addWorker</code>方法调用addWorker方法源码下半部分中的第4步<code>t.start</code>,会触发<code>Worker</code>类的<code>run</code>方法被JVM调用。</p><p>我们再看看<code>runWorker</code>的逻辑:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// Worker.runWorker方法源代码</span>
<span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">runWorker</span><span class="token punctuation">(</span><span class="token class-name">Worker</span> w<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Thread</span> wt <span class="token operator">=</span> <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Runnable</span> task <span class="token operator">=</span> w<span class="token punctuation">.</span>firstTask<span class="token punctuation">;</span>
w<span class="token punctuation">.</span>firstTask <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token comment">// 1.线程启动之后,通过unlock方法释放锁</span>
w<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// allow interrupts</span>
<span class="token keyword">boolean</span> completedAbruptly <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 2.Worker执行firstTask或从workQueue中获取任务,如果getTask方法不返回null,循环不退出</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>task <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token punctuation">(</span>task <span class="token operator">=</span> <span class="token function">getTask</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 2.1进行加锁操作,保证thread不被其他线程中断(除非线程池被中断)</span>
w<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// If pool is stopping, ensure thread is interrupted;</span>
<span class="token comment">// if not, ensure thread is not interrupted. This</span>
<span class="token comment">// requires a recheck in second case to deal with</span>
<span class="token comment">// shutdownNow race while clearing interrupt</span>
<span class="token comment">// 2.2检查线程池状态,倘若线程池处于中断状态,当前线程将中断。 </span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token function">runStateAtLeast</span><span class="token punctuation">(</span>ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> STOP<span class="token punctuation">)</span> <span class="token operator">||</span>
<span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&&</span>
<span class="token function">runStateAtLeast</span><span class="token punctuation">(</span>ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> STOP<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&&</span>
<span class="token operator">!</span>wt<span class="token punctuation">.</span><span class="token function">isInterrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
wt<span class="token punctuation">.</span><span class="token function">interrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 2.3执行beforeExecute </span>
<span class="token function">beforeExecute</span><span class="token punctuation">(</span>wt<span class="token punctuation">,</span> task<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Throwable</span> thrown <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 2.4执行任务</span>
task<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">RuntimeException</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
thrown <span class="token operator">=</span> x<span class="token punctuation">;</span> <span class="token keyword">throw</span> x<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Error</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
thrown <span class="token operator">=</span> x<span class="token punctuation">;</span> <span class="token keyword">throw</span> x<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
thrown <span class="token operator">=</span> x<span class="token punctuation">;</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
<span class="token comment">// 2.5执行afterExecute方法 </span>
<span class="token function">afterExecute</span><span class="token punctuation">(</span>task<span class="token punctuation">,</span> thrown<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
task <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
w<span class="token punctuation">.</span>completedTasks<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token comment">// 2.6解锁操作</span>
w<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
completedAbruptly <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
<span class="token function">processWorkerExit</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> completedAbruptly<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>首先去执行创建这个worker时就有的任务,当执行完这个任务后,worker的生命周期并没有结束,在<code>while</code>循环中,worker会不断地调用<code>getTask</code>方法从<strong>阻塞队列</strong>中获取任务然后调用<code>task.run()</code>执行任务,从而达到<strong>复用线程</strong>的目的。只要<code>getTask</code>方法不返回<code>null</code>,此线程就不会退出。</p><p>当然,核心线程池中创建的线程想要拿到阻塞队列中的任务,先要判断线程池的状态,如果<strong>STOP</strong>或者<strong>TERMINATED</strong>,返回<code>null</code>。</p><p>最后看看<code>getTask</code>方法的实现:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// Worker.getTask方法源码</span>
<span class="token keyword">private</span> <span class="token class-name">Runnable</span> <span class="token function">getTask</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">boolean</span> timedOut <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">// Did the last poll() time out?</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> rs <span class="token operator">=</span> <span class="token function">runStateOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Check if queue empty only if necessary.</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>rs <span class="token operator">>=</span> SHUTDOWN <span class="token operator">&&</span> <span class="token punctuation">(</span>rs <span class="token operator">>=</span> STOP <span class="token operator">||</span> workQueue<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">decrementWorkerCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">int</span> wc <span class="token operator">=</span> <span class="token function">workerCountOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Are workers subject to culling?</span>
<span class="token comment">// 1.allowCoreThreadTimeOut变量默认是false,核心线程即使空闲也不会被销毁</span>
<span class="token comment">// 如果为true,核心线程在keepAliveTime内仍空闲则会被销毁。 </span>
<span class="token keyword">boolean</span> timed <span class="token operator">=</span> allowCoreThreadTimeOut <span class="token operator">||</span> wc <span class="token operator">></span> corePoolSize<span class="token punctuation">;</span>
<span class="token comment">// 2.如果运行线程数超过了最大线程数,但是缓存队列已经空了,这时递减worker数量。 </span>
<span class="token comment">// 如果有设置允许线程超时或者线程数量超过了核心线程数量,</span>
<span class="token comment">// 并且线程在规定时间内均未poll到任务且队列为空则递减worker数量</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>wc <span class="token operator">></span> maximumPoolSize <span class="token operator">||</span> <span class="token punctuation">(</span>timed <span class="token operator">&&</span> timedOut<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token operator">&&</span> <span class="token punctuation">(</span>wc <span class="token operator">></span> <span class="token number">1</span> <span class="token operator">||</span> workQueue<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">compareAndDecrementWorkerCount</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">continue</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 3.如果timed为true(想想哪些情况下timed为true),则会调用workQueue的poll方法获取任务.</span>
<span class="token comment">// 超时时间是keepAliveTime。如果超过keepAliveTime时长,</span>
<span class="token comment">// poll返回了null,上边提到的while循序就会退出,线程也就执行完了。</span>
<span class="token comment">// 如果timed为false(allowCoreThreadTimeOut为false</span>
<span class="token comment">// 且wc > corePoolSize为false),则会调用workQueue的take方法阻塞在当前。</span>
<span class="token comment">// 队列中有任务加入时,线程被唤醒,take方法返回任务,并执行。</span>
<span class="token class-name">Runnable</span> r <span class="token operator">=</span> timed <span class="token operator">?</span>
workQueue<span class="token punctuation">.</span><span class="token function">poll</span><span class="token punctuation">(</span>keepAliveTime<span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span>NANOSECONDS<span class="token punctuation">)</span> <span class="token operator">:</span>
workQueue<span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>r <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> r<span class="token punctuation">;</span>
timedOut <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> retry<span class="token punctuation">)</span> <span class="token punctuation">{</span>
timedOut <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>核心线程的会一直卡在<code>workQueue.take</code>方法,被阻塞并挂起,不会占用CPU资源,直到拿到<code>Runnable</code> 然后返回(当然如果<strong>allowCoreThreadTimeOut</strong>设置为<code>true</code>,那么核心线程就会去调用<code>poll</code>方法,因为<code>poll</code>可能会返回<code>null</code>,所以这时候核心线程满足超时条件也会被销毁)。</p><p>非核心线程会workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) ,如果超时还没有拿到,下一次循环判断<strong>compareAndDecrementWorkerCount</strong>就会返回<code>null</code>,Worker对象的<code>run()</code>方法循环体的判断为<code>null</code>,任务结束,然后线程被系统回收 。</p><p>源码解析完毕,你理解的源码是否和图中的处理流程一致?如果不一致,那么就多看两遍吧,加油。</p><h2 id="四种常见的线程池" tabindex="-1"><a class="header-anchor" href="#四种常见的线程池" aria-hidden="true">#</a> 四种常见的线程池</h2><p><code>Executors</code>类中提供的几个静态方法来创建线程池。大家到了这一步,如果看懂了前面讲的<code>ThreadPoolExecutor</code>构造方法中各种参数的意义,那么一看到<code>Executors</code>类中提供的线程池的源码就应该知道这个线程池是干嘛的。</p><h3 id="newcachedthreadpool" tabindex="-1"><a class="header-anchor" href="#newcachedthreadpool" aria-hidden="true">#</a> newCachedThreadPool</h3><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ExecutorService</span> <span class="token function">newCachedThreadPool</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span>MAX_VALUE<span class="token punctuation">,</span>
<span class="token number">60L</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span>SECONDS<span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">SynchronousQueue</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Runnable</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>CacheThreadPool</code>的<strong>运行流程</strong>如下:</p><ol><li>提交任务进线程池。</li><li>因为<strong>corePoolSize</strong>为0的关系,不创建核心线程,线程池最大为Integer.MAX_VALUE。</li><li>尝试将任务添加到<strong>SynchronousQueue</strong>队列。</li><li>如果SynchronousQueue入列成功,等待被当前运行的线程空闲后拉取执行。如果当前没有空闲线程,那么就创建一个非核心线程,然后从SynchronousQueue拉取任务并在当前线程执行。</li><li>如果SynchronousQueue已有任务在等待,入列操作将会阻塞。</li></ol><p>当需要执行很多<strong>短时间</strong>的任务时,CacheThreadPool的线程复用率比较高, 会显著的<strong>提高性能</strong>。而且线程60s后会回收,意味着即使没有任务进来,CacheThreadPool并不会占用很多资源。</p><h3 id="newfixedthreadpool" tabindex="-1"><a class="header-anchor" href="#newfixedthreadpool" aria-hidden="true">#</a> newFixedThreadPool</h3><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ExecutorService</span> <span class="token function">newFixedThreadPool</span><span class="token punctuation">(</span><span class="token keyword">int</span> nThreads<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span>nThreads<span class="token punctuation">,</span> nThreads<span class="token punctuation">,</span>
<span class="token number">0L</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span>MILLISECONDS<span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">LinkedBlockingQueue</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Runnable</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>核心线程数量和总线程数量相等,都是传入的参数nThreads,所以只能创建核心线程,不能创建非核心线程。因为LinkedBlockingQueue的默认大小是Integer.MAX_VALUE,故如果核心线程空闲,则交给核心线程处理;如果核心线程不空闲,则入列等待,直到核心线程空闲。</p><p><strong>与CachedThreadPool的区别</strong>:</p><ul><li>因为 corePoolSize == maximumPoolSize ,所以FixedThreadPool只会创建核心线程。 而CachedThreadPool因为corePoolSize=0,所以只会创建非核心线程。</li><li>在 getTask() 方法,如果队列里没有任务可取,线程会一直阻塞在 LinkedBlockingQueue.take() ,线程不会被回收。 CachedThreadPool会在60s后收回。</li><li>由于线程不会被回收,会一直卡在阻塞,所以<strong>没有任务的情况下, FixedThreadPool占用资源更多</strong>。</li><li>都几乎不会触发拒绝策略,但是原理不同。FixedThreadPool是因为阻塞队列可以很大(最大为Integer最大值),故几乎不会触发拒绝策略;CachedThreadPool是因为线程池很大(最大为Integer最大值),几乎不会导致线程数量大于最大线程数,故几乎不会触发拒绝策略。</li></ul><h3 id="newsinglethreadexecutor" tabindex="-1"><a class="header-anchor" href="#newsinglethreadexecutor" aria-hidden="true">#</a> newSingleThreadExecutor</h3><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ExecutorService</span> <span class="token function">newSingleThreadExecutor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">FinalizableDelegatedExecutorService</span>
<span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token number">0L</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span>MILLISECONDS<span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">LinkedBlockingQueue</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Runnable</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>有且仅有一个核心线程( corePoolSize == maximumPoolSize=1),使用了LinkedBlockingQueue(容量很大),所以,<strong>不会创建非核心线程</strong>。所有任务按照<strong>先来先执行</strong>的顺序执行。如果这个唯一的线程不空闲,那么新来的任务会存储在任务队列里等待执行。</p><h3 id="newscheduledthreadpool" tabindex="-1"><a class="header-anchor" href="#newscheduledthreadpool" aria-hidden="true">#</a> newScheduledThreadPool</h3><p>创建一个定长线程池,支持定时及周期性任务执行。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ScheduledExecutorService</span> <span class="token function">newScheduledThreadPool</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ScheduledThreadPoolExecutor</span><span class="token punctuation">(</span>corePoolSize<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//ScheduledThreadPoolExecutor():</span>
<span class="token keyword">public</span> <span class="token class-name">ScheduledThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>corePoolSize<span class="token punctuation">,</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span>MAX_VALUE<span class="token punctuation">,</span>
DEFAULT_KEEPALIVE_MILLIS<span class="token punctuation">,</span> MILLISECONDS<span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">DelayedWorkQueue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>四种常见的线程池基本够我们使用了,但是《阿里巴巴开发手册》不建议我们直接使用Executors类中的线程池,而是通过<code>ThreadPoolExecutor</code>的方式,这样的处理方式让写的同学需要更加明确线程池的运行规则,规避资源耗尽的风险。</p><p>但如果你及团队本身对线程池非常熟悉,又确定业务规模不会大到资源耗尽的程度(比如线程数量或任务队列长度可能达到Integer.MAX_VALUE)时,其实是可以使用JDK提供的这几个接口的,它能让我们的代码具有更强的可读性。</p><hr><blockquote><p>编辑:沉默王二,内容大部分来源以下三个开源仓库:</p><ul><li><a href="http://concurrent.redspider.group/" target="_blank" rel="noopener noreferrer">深入浅出 Java 多线程<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li><li><a href="https://github.com/CL0610/Java-concurrency" target="_blank" rel="noopener noreferrer">并发编程知识总结<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li><li><a href="https://github.com/CoderLeixiaoshuai/java-eight-part" target="_blank" rel="noopener noreferrer">Java八股文<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li></ul></blockquote><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png"></div><!----><footer class="page-meta"><div class="meta-item edit-link"><a href="https://github.com/itwanger/toBeBetterJavaer/edit/master/docs/thread/pool.md" rel="noopener noreferrer" target="_blank" aria-label="在 GitHub 上编辑此页" class="nav-link label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="edit icon"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></svg><!--]-->在 GitHub 上编辑此页<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="meta-item update-time"><span class="label">上次编辑于: </span><span class="info">2022/5/12 下午4:24:21</span></div><div class="meta-item contributors"><span class="label">贡献者: </span><!--[--><!--[--><span class="contributor" title="email: [email protected]">itwanger</span>,<!--]--><!--[--><span class="contributor" title="email: [email protected]">沉默王二</span><!--]--><!--]--></div></footer><nav class="page-nav"><a href="/thread/BlockingQueue.html" class="nav-link prev" aria-label="BlockingQueue"><div class="hint"><span class="arrow left"></span>上一页</div><div class="link"><!---->BlockingQueue</div></a><a href="/thread/ScheduledThreadPoolExecutor.html" class="nav-link next" aria-label="计划任务"><div class="hint">下一页<span class="arrow right"></span></div><div class="link">计划任务<!----></div></a></nav><div class="giscus-wrapper input-top" style="display:block;">Loading...</div><!----><!--]--></main><!--]--><footer class="footer-wrapper"><div class="footer"><a href="https://beian.miit.gov.cn/" target="_blank">豫ICP备2021038026号-1</a><img src="https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/beian.png" height="15px" width="15px" /><a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=41030502000411"><span>豫公网安备 41030502000411号</span></a></div><div class="copyright">Copyright © 2022 沉默王二</div></footer><!--]--></div><!--]--><!----><!----><!--]--></div>
<script type="module" src="/assets/app.41bad062.js" defer></script>
</body>
</html>