1- ![ ] ( https://ws1.sinaimg.cn/large/006tKfTcgy1ftpwh3a2szj31kw11xh84 .jpg )
1+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2a867bea .jpg )
22
33## 前言
44
55平时接触过多线程开发的童鞋应该都或多或少了解过线程池,之前发布的《阿里巴巴 Java 手册》里也有一条:
66
7- ![ ] ( https://ws2.sinaimg.cn/large/006tKfTcgy1ftpxf3x1epj30la03s0tl .jpg )
7+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2a8dad64 .jpg )
88
99可见线程池的重要性。
1010
2626- ` Executors.newFixedThreadPool(nThreads) ` :创建固定大小的线程池。
2727- ` Executors.newSingleThreadExecutor() ` :创建单个线程的线程池。
2828
29+ <!-- more-->
2930
3031其实看这三种方式创建的源码就会发现:
3132
@@ -67,7 +68,7 @@ threadPool.execute(new Job());
6768
6869在具体分析之前先了解下线程池中所定义的状态,这些状态都和线程的执行密切相关:
6970
70- ![ ] ( https://ws3.sinaimg.cn/large/006tKfTcgy1ftq1ks5qywj30jn03i3za .jpg )
71+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2a9bc566 .jpg )
7172
7273- ` RUNNING ` 自然是运行状态,指可以接受任务执行队列里的任务
7374- ` SHUTDOWN ` 指调用了 ` shutdown() ` 方法,不再接受新任务了,但是队列里的任务得执行完毕。
@@ -77,22 +78,22 @@ threadPool.execute(new Job());
7778
7879用图表示为:
7980
80- ![ ] ( https://ws4.sinaimg.cn/large/006tKfTcgy1ftq2nxlwe5j30sp0ba0ts .jpg )
81+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2aa81655 .jpg )
8182
8283然后看看 ` execute() ` 方法是如何处理的:
8384
84- ![ ] ( https://ws1.sinaimg.cn/large/006tKfTcgy1ftq283zi91j30ky08mwgb .jpg )
85+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2ab921db .jpg )
8586
86871 . 获取当前线程池的状态。
87882 . 当前线程数量小于 coreSize 时创建一个新的线程运行。
88893 . 如果当前线程处于运行状态,并且写入阻塞队列成功。
89- 4 . 双重检查,再次获取线程池状态;如果线程池状态变了 (非运行状态)就需要从阻塞队列移除任务,并尝试判断线程是否全部执行完毕。同时执行拒绝策略。
90+ 4 . 双重检查,再次获取线程状态;如果线程状态变了 (非运行状态)就需要从阻塞队列移除任务,并尝试判断线程是否全部执行完毕。同时执行拒绝策略。
90915 . 如果当前线程池为空就新创建一个线程并执行。
91926 . 如果在第三步的判断为非运行状态,尝试新建线程,如果失败则执行拒绝策略。
9293
9394这里借助《聊聊并发》的一张图来描述这个流程:
9495
95- ![ ] ( https://ws4.sinaimg.cn/large/006tKfTcgy1ftq2vzuv5rj30dw085q3i .jpg )
96+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2ac0936c .jpg )
9697
9798
9899### 如何配置线程
@@ -206,16 +207,16 @@ public class TreadPoolConfig {
206207
207208其实 ThreadPool 本身已经提供了不少 api 可以获取线程状态:
208209
209- ![ ] ( https://ws1.sinaimg.cn/large/006tKfTcgy1ftq3xsrbs6j30bg0bpgnb .jpg )
210+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2accbbcf .jpg )
210211
211212很多方法看名字就知道其含义,只需要将这些信息暴露到 SpringBoot 的监控端点中,我们就可以在可视化页面查看当前的线程池状态了。
212213
213214
214215甚至我们可以继承线程池扩展其中的几个函数来自定义监控逻辑:
215216
216- ![ ] ( https://ws2.sinaimg.cn/large/006tKfTcgy1ftq40lkw9jj30mq07rmyt .jpg )
217+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2add4d31 .jpg )
217218
218- ![ ] ( https://ws4.sinaimg.cn/large/006tKfTcgy1ftq41asf8rj30kq07cabd .jpg )
219+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2aeea439 .jpg )
219220
220221看这些名称和定义都知道,这是让子类来实现的。
221222
@@ -383,7 +384,7 @@ public class CommandUser extends HystrixCommand<String> {
383384
384385运行结果:
385386
386- ![ ] ( https://ws2.sinaimg.cn/large/006tKfTcgy1ftq4e0ukubj30ps04gtak .jpg )
387+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2b06ef2d .jpg )
387388
388389可以看到两个任务分成了两个线程池运行,他们之间互不干扰。
389390
@@ -397,7 +398,7 @@ public class CommandUser extends HystrixCommand<String> {
397398
398399通过刚才的构造函数也能证明:
399400
400- ![ ] ( https://ws2.sinaimg.cn/large/006tKfTcgy1ftq4i6xy2qj30uo09adhp .jpg )
401+ ![ ] ( https://i.loli.net/2019/05/08/5cd1d2b69cd32 .jpg )
401402
402403还要注意的一点是:
403404
@@ -409,4 +410,4 @@ public class CommandUser extends HystrixCommand<String> {
409410
410411文末的 hystrix 源码:
411412
412- [ https://github.com/crossoverJie/Java-Interview/tree/master/src/main/java/com/crossoverjie/hystrix ] ( https://github.com/crossoverJie/Java-Interview/tree/master/src/main/java/com/crossoverjie/hystrix )
413+ [ https://github.com/crossoverJie/Java-Interview/tree/master/src/main/java/com/crossoverjie/hystrix ] ( https://github.com/crossoverJie/Java-Interview/tree/master/src/main/java/com/crossoverjie/hystrix )
0 commit comments