Skip to content

Commit 057ab51

Browse files
committed
ThreadPoolExecutor: 基本任务处理流程
1 parent fb9e0fb commit 057ab51

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

java/ThreadPoolExecutor源码剖析.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,49 @@
147147

148148
## 任务处理流程
149149

150+
我们以一个简单例子来剖析一下整个过程。
151+
152+
```java
153+
154+
package me.rainstorm;
155+
156+
import java.util.concurrent.ExecutorService;
157+
import java.util.concurrent.LinkedBlockingDeque;
158+
import java.util.concurrent.ThreadPoolExecutor;
159+
import java.util.concurrent.TimeUnit;
160+
161+
/**
162+
*
163+
* @author baochen.zhang
164+
* @date 2017.12.4
165+
*/
166+
public class ThreadPoolExecutorDemo {
167+
private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors() + 2;
168+
private static ExecutorService exe = new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE,
169+
60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(100));
170+
171+
{
172+
((ThreadPoolExecutor)exe).allowCoreThreadTimeOut(true);
173+
}
174+
175+
public static void main(String[] args) {
176+
exe.execute(() -> System.out.println("Hello world"));
177+
178+
exe.shutdown();
179+
exe = null;
180+
}
181+
}
182+
183+
```
184+
185+
![](../res/thread-pool-executor-demo.png)
186+
187+
1. `ctl` 变量之前已经提到了,作为一个控制变量用来控制线程池的状态和工作线程数。默认值是 `RUNNING | 0`,即状态为 `RUNNING`,Worker 线程数为 0;
188+
1. 在 Demo 中并未指定线程工厂,`ThreadPoolExecutor` 使用 `Executors` 提供的默认线程工厂。
189+
1. 因为只有一个任务,所以 `main` 方法中在提交完这个任务后,直接调用了 `shutdown()` 方法,并将其赋为 `null` 便于在任务执行完毕后回收资源,一般情况下推荐在所有任务都提交到线程池以后再调用 `shutdown`,否则之后的任务直接会被拒绝掉。
190+
1. 因为只有一个任务,且允许核心线程超时,所以该线程在 `getTask()` 过程中会超时,然后返回 `null`,进入 `processWorkerExit()` 流程。
191+
1. 线程池在进入 `TERMINATED` 状态后就可以被 GC 了。
192+
150193
## 最佳实践
151194

152195
一般情况下使用 `Executors` 的工厂方法来创建即可适用于大多数场景。需要配置的话参考 个性定制 来配置更合适自己项目的 `ThreadPoolExecutor`
@@ -161,3 +204,4 @@
161204
1. [Java SE 9 & JDK 9 -- Source Code](.)
162205
1. [What is Daemon thread in Java?](https://stackoverflow.com/questions/2213340/what-is-daemon-thread-in-java)
163206
1. [深入理解java线程池—ThreadPoolExecutor](http://www.jianshu.com/p/ade771d2c9c0)
207+
1. [Java 中, 为什么一个对象的实例方法在执行完成之前其对象可以被 GC 回收?](https://www.zhihu.com/question/51244545)

res/thread-pool-executor-demo.png

103 KB
Loading

res/thread-pool-executor-demo.pu

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
@startuml thread-pool-executor-demo
2+
3+
participant ThreadPoolExecutorDemo
4+
participant ThreadPoolExecutor
5+
participant Worker
6+
participant Thread
7+
participant Executors
8+
participant DefaultThreadFactory
9+
10+
ThreadPoolExecutorDemo -> ThreadPoolExecutor : new ThreadPoolExecutor();
11+
activate ThreadPoolExecutor
12+
ThreadPoolExecutor -> ThreadPoolExecutor : ctl = new AtomicInteger(ctlOf(RUNNING, 0));
13+
activate ThreadPoolExecutor
14+
deactivate ThreadPoolExecutor
15+
ThreadPoolExecutor -> Executors : Executors.defaultThreadFactory()
16+
ThreadPoolExecutor <-- DefaultThreadFactory : java.util.concurrent.Executors.DefaultThreadFactory;
17+
ThreadPoolExecutorDemo <-- ThreadPoolExecutor : ThreadPoolExecutor instance
18+
deactivate ThreadPoolExecutor
19+
20+
...
21+
22+
ThreadPoolExecutorDemo -> ThreadPoolExecutor : allowCoreThreadTimeOut(true)
23+
24+
...
25+
26+
ThreadPoolExecutorDemo -> ThreadPoolExecutor: execute(command);
27+
activate ThreadPoolExecutor
28+
ThreadPoolExecutor -> ThreadPoolExecutor : addWorker(command, true)
29+
activate ThreadPoolExecutor
30+
ThreadPoolExecutor -> Worker: new Worker(command);
31+
activate Worker
32+
Worker -> DefaultThreadFactory : newThread(this);
33+
Worker <-- DefaultThreadFactory : Thread instance
34+
ThreadPoolExecutor <-- Worker : Worker instance
35+
deactivate Worker
36+
ThreadPoolExecutor -> ThreadPoolExecutor : workers.add(worker)
37+
ThreadPoolExecutor -> Thread : Thread start()
38+
deactivate ThreadPoolExecutor
39+
deactivate ThreadPoolExecutor
40+
41+
ThreadPoolExecutorDemo -> ThreadPoolExecutor : shutdown()
42+
activate ThreadPoolExecutor
43+
ThreadPoolExecutor -> ThreadPoolExecutor : advanceRunState(SHUTDOWN);
44+
deactivate ThreadPoolExecutor
45+
46+
... worker thread start ...
47+
48+
Thread -> Worker : run()
49+
activate Worker
50+
Worker -> ThreadPoolExecutor : runWorker(this);
51+
activate ThreadPoolExecutor
52+
ThreadPoolExecutor -> ThreadPoolExecutor : beforeExecute(wt, task);
53+
ThreadPoolExecutor -> command : run()
54+
activate command
55+
note over command
56+
需要执行的任务,当前任务是
57+
System.out.println("Hello world");
58+
end note
59+
deactivate command
60+
ThreadPoolExecutor -> ThreadPoolExecutor : afterExecute(task, thrown);
61+
ThreadPoolExecutor -> ThreadPoolExecutor : getTask()
62+
activate ThreadPoolExecutor
63+
ThreadPoolExecutor -> ThreadPoolExecutor : compareAndDecrementWorkerCount()
64+
deactivate ThreadPoolExecutor
65+
ThreadPoolExecutor -> ThreadPoolExecutor : processWorkerExit()
66+
activate ThreadPoolExecutor
67+
ThreadPoolExecutor -> ThreadPoolExecutor : tryTerminate()
68+
activate ThreadPoolExecutor
69+
ThreadPoolExecutor -> ThreadPoolExecutor : ctl.compareAndSet(c, ctlOf(TIDYING, 0))
70+
ThreadPoolExecutor -> ThreadPoolExecutor : terminated()
71+
ThreadPoolExecutor -> ThreadPoolExecutor : ctl.set(ctlOf(TERMINATED, 0));
72+
deactivate ThreadPoolExecutor
73+
deactivate ThreadPoolExecutor
74+
deactivate ThreadPoolExecutor
75+
deactivate Worker
76+
77+
@enduml

0 commit comments

Comments
 (0)