Skip to content

Commit b16f324

Browse files
authored
Merge pull request h2pl#25 from Rorke76753/patch-1
Update Java并发指南12:深度解读 java 线程池设计思想及源码实现.md
2 parents 65e029b + d016975 commit b16f324

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

docs/java/currency/Java并发指南12:深度解读 java 线程池设计思想及源码实现.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* [AbstractExecutorService](#abstractexecutorservice)
99
* [ThreadPoolExecutor](#threadpoolexecutor)
1010
* [Executors](#executors)
11+
* [Worker获取任务](#getTask)
1112
* [总结](#总结)
1213

1314

@@ -1275,6 +1276,51 @@ else if (!addWorker(command, false))
12751276

12761277
> SynchronousQueue 是一个比较特殊的 BlockingQueue,其本身不储存任何元素,它有一个虚拟队列(或虚拟栈),不管读操作还是写操作,如果当前队列中存储的是与当前操作相同模式的线程,那么当前操作也进入队列中等待;如果是相反模式,则配对成功,从当前队列中取队头节点。具体的信息,可以看我的另一篇关于 BlockingQueue 的文章。
12771278
1279+
## getTask
1280+
前文已经分析了`runWorker`方法,我们可以看到该方法中有一行这样的代码
1281+
```java
1282+
//...
1283+
while (task != null || (task = getTask()) != null) {
1284+
//...
1285+
```
1286+
这一行代码如果`task!=null`,即前一个条件为`true`时意味着传入的一个非`null`的`task`,同时代码会优化使得第二个条件不去执行;那么前一个条件为`false`时,就会尝试调用`getTask`方法。在这一个方法中,`worker`会尝试从工作队列中取出任务来进行执行。
1287+
```java
1288+
private Runnable getTask() {
1289+
boolean timedOut = false;
1290+
//不断尝试获得任务
1291+
for (;;) {
1292+
int c = ctl.get();
1293+
int rs = runStateOf(c);
1294+
// 前文已有相似的状态,这里不再赘述
1295+
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
1296+
decrementWorkerCount();
1297+
return null;
1298+
}
1299+
int wc = workerCountOf(c);
1300+
//是否设置了允许核心线程超时(设置了之后核心线程在超时后会销毁),或者当前worker数量比核心池大
1301+
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
1302+
1303+
if ((wc > maximumPoolSize || (timed && timedOut))&& (wc > 1 || workQueue.isEmpty())) {
1304+
if (compareAndDecrementWorkerCount(c))
1305+
return null;
1306+
continue;
1307+
}
1308+
try {
1309+
//是否设置了允许核心线程超时(设置了之后核心线程在超时后会销毁),或者当前worker数量比核心池大
1310+
//如果是调用queue的poll(int,TimeUnit)方法,否则直接调用take方法
1311+
Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
1312+
//能获取到非空的任务就返回
1313+
//对于不设置允许核心线程超时的情况,核心线程就一直在getTask的这个循环中
1314+
//一直等待有新的任务来执行
1315+
if (r != null)
1316+
return r;
1317+
timedOut = true;
1318+
} catch (InterruptedException retry) {
1319+
timedOut = false;
1320+
}
1321+
}
1322+
}
1323+
```
12781324
## 总结
12791325

12801326
我一向不喜欢写总结,因为我把所有需要表达的都写在正文中了,写小篇幅的总结并不能真正将话说清楚,本文的总结部分为准备面试的读者而写,希望能帮到面试者或者没有足够的时间看完全文的读者。

0 commit comments

Comments
 (0)