java并发线程池ThreadPoolExecutor深入剖析最
本文为原创文章,转载请注明出处,谢谢你……
> 喜欢java并发编程的请加群:736156823
开始-->
先吐槽:
网上有很多介绍线程池的文章,都是抄的,没劲,没一个流程图,没有一个是从submit开始到内部流转在到执行的,像我这种小白能看懂?老奶奶能看懂吗?就连这么有生活阅历的人都看不懂,你写他还有什么用呢?不是在浪费资源吗?反正上来就是先吐槽,自己爽了,然后再说。但是我觉得这个吐槽还不给力,所以就直接写一篇文章吧。哈哈,上述都是废话,没什么用处,乐呵乐呵就好了,哈哈……
直接干:
1.环境:为了靠谱点,装了个最新的jdk,哎呀,好麻烦,烦躁……版本:jdk-8u121-windows-x64;
2.继承关系:
ThreadPoolExecutor继承结构3.创建ThreadPoolExecutor后直接提交runnable的流程图如下:
ThreadPoolExecutor中submit流程图说明:其中的什么接口啦,什么实现类啊,靠,不说了,没劲……然后就是生成runnableFuture对象的方法,太简单了……然后基本就没啥了,关键是要有流程图,有了这个谁还愿意看代码?而且就只是那干巴巴的代码一摆就得了?哼……没劲……下面给出源代码截图:
submit源代码 构造RunnableFuture源代码4.ThreadPoolExecutor中的execute方法流程图:
execute方法流程图 execute方法源代码说明:
1)针对AtomicInteger类型ctl参数的说明,ctl是一个 AtomicInteger 类型, 它的低29位用于存放当前的线程数, 因此一个线程池在理论上最大的线程数是536870911; 高 3 位是用于表示当前线程池的状态, 其中高三位的值和状态对应如下:
111: RUNNING;
000: SHUTDOWN;
001: STOP;
010: TIDYING;
110: TERMINATED;
2)workerCountOf方法获取线程池当前有效的线程数量,实现很简单,不说了;
3)corePoolSize,核心线程数。当线程池中的任务缓存队列还没有被填充满时,线程池中允许的最多的有效的线程数量;
4)addWorker方法,正真的将任务添加到线程池,并且执行启动线程即调用Thread.start()方法的方法。内部执行流程会在下面给出;
5)isRunning方法,判断线程池状态的方法。实现简单,不说了;
6)remove方法,移除任务。简单,不说了,至于内部的tryTerminate方法,后面给出;
7)reject方法,线程池如何拒绝任务提交的方法策略。这个和线程池的初始化参数有关,后面介绍,也比较简单,不多说。
8)为什么要这么多的判断?判断这些又有什么用呢?
“workerCountOf(c) < corePoolSize”判断,主要为了判断当前线程池中活跃线程的数量是否大于核心线程数,如果大于那么会将这个任务方到阻塞队列中,如果小于那么就会直接创建新的线程去执行;如果调用addworker方法成功了,那么就直接返回了,如果失败了就重新获取当前线程数量继续执行下面的代码。
“isRunning(c) && workQueue.offer(command)”这个判断,主要是为了判断当前线程池是否是活跃的,并且在这种情况下能否提交任务成功,如果当前线程池不活跃,那么会继续下面的其他判断;如果当前的状态是活跃的,那么会将任务提交到队列中,如果提交失败同样会继续下面其他的判断,如果提交成功会进入内部判断;
“! isRunning(recheck) && remove(command)”这个判断,提交队列成功后在此次判断当前线程池的状态,如果被关闭,那么将任务删除,再调用拒绝策略;
“workerCountOf(recheck) == 0”这个判断,主要为了防止所有线程恰好在新的任务提交成功后却都到了最大存活时间而消亡了,造成没有线程到队列中去取任务执行,为了防止bug出现,哈哈;
“!addWorker(command, false)”这个判断主要为了处理在队列被填满,但是活跃的线程数还没有达到最大线程数maximumPoolSize的情况,如果这个也失败了,那就拒绝了。
这些判断还有一些其他的作用,要整体来看,这里给出主要作用,后面会补充,如果你从头到尾看完此文章,这些整体上的作用相信你也会体会到的。
execute整体流程说明如下图:
execute整体流程说明Part1 execute整体流程说明Part25.addWorker方法流程图:
addWorker方法流程图再补一个同样的流程,上面的是图片,简书有时候刷不出来,编辑都出不来,哎……
addWorker方法流程图(副本)说明:
1)针对上图中的菱形条件判断,顺序是以从上到下,从左到右为顺序;
2)第一条件判断,源代码如下图:
条件判断0首先,如果‘rs >= SHUTDOWN’结果为false,那么将不会继续下面的判断,那么会继续走下面的流程,因为结果为false说明当前线程池还是可提交(运行)状态,所以直接继续,并不执行return false语句。第二种情况,如果第一个判断为true,那么进入if的下一个判断‘! (rs == SHUTDOWN &&firstTask == null &&! workQueue.isEmpty())’,因为第一个判断为true,所以rs的值可能rs = = SHUTDOWN或者rs > SHUTDOWN,如果rs == SHUTDOWN,那么内部的判断将会继续,会继续判断firstTask==null,如果为null那么继续向下判断! workQueue.isEmpty(),说了这么多,有没有感觉很乱,是的我都乱了,所以,还是直接翻译成流程图吧……哈哈,好期待,下面给出第一个菱形条件判断的流程图:
第一个条件判断的判断流程说明:上图是第一个条件判断语句if里面的内容,具体转换,往下看。
下面给出代码上的转换:
第一个条件判断在代码上的转换说明:上图中上面注释调的部分为源代码。其中源代码中的执行流程被返回的true替代了,这里就是示意一下。就不进行文字描述了,流程图已经说得很明白了,如果图还看不懂的话,老衲也无能为力了,还请师太帮忙……哈哈……。其实上面注意的是那些变量的判断,为什么要那样判断呢?这个问题和线程池的整体策略有关,要全部说完才行,先记下来,接着往下说。
3)第二个菱形条件判断源代码:
第二个条件判断源代码判断流程代码转换:
第二个条件判断流程代码转换判断的具体流程图:
第二个条件判断的流程图说明:
4)第五个菱形条件判断源代码:
第五个菱形条件判断源代码形式上的代码转换如下:
第五个菱形判断的代码转换使用流程图表示如下:
第五个菱形判断的流程图说明:太简单了,代码转换,流程图看起来很容易,不解释了。
5)简单总结一下:在addWorker中的主要的流程判断都已经给出,其他的很简单的就不说明了。其实,这里面比这些判断还重要的是为什么要进行这样的判断和判断这些是为了什么?还有一个比较重要的是addWorker方法了里面调用的一些其他的内部方法,所以请好好看下针对每个判断下面的说明,重点介绍了为什么要那么判断,原因理由目的。是的,如果上面的针对判断的说明没有介绍的太清楚或者还有什么疏漏,这些后面都还会有详细的补充介绍并加以说明。下面给出addWorker的源代码截图:
addWorker方法源代码6)整体代码说明:
addWorker代码说明part1 addWorker代码说明part2好了,先告一段落,继续下面的方法。
6.tryTerminate方法流程
tryTerminate方法流程图说明:
1.全部说明见下图:
tryTerminate方法流程说明7.processWorkerExit方法流程
processWorkerExit方法流程图说明:
processWorkerExit方法流程说明8.getTask方法流程
getTask方法流程图说明:
getTask方法说明Part1 getTask方法说明Part2 getTask方法说明Part39.runWorker方法流程
runWorker方法流程图说明:
runWorker方法流程说明Part1 runWorker方法流程说明Part2 runWorker方法流程说明Part3>下面给出本人的代码github地址:
https://github.com/baojie5642/hahathreadpool
> 喜欢java并发编程的请加群:736156823
大大的总结:
这篇文章很早就创建了,但是一致没搭理,最开始是eclipse,后面确实idea,本文格式太丑(自己讨太蠢了),哈哈……
文章里面的错误欢迎大家指正,么么哒……
后面补上的内容是使用的jdk8最新64版本代码……
本文为原创文章,转载请注明出处,谢谢你……
结束-->
哈哈给您请安了……
拜拜……