线程池源码浅析
Posted 猿必学
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池源码浅析相关的知识,希望对你有一定的参考价值。
前言:第一次写源码分析类文章,有点忐忑,还是硬着头皮上了。 之前几篇线程池文章主要是讲解线程池使用场景,这篇文章我以非代码方式讲解源码,这个估计没人这么干过吧!哈哈。
说实话一打开那种源码帖,不够耐心真心看不完,而且也记不住啊,之前学过一段时间的《记忆法》,最强大脑里面的冠军 袁文魁写了一本书专门讲记忆方法的书,里面说图形记忆是最快,记忆比较难忘的一种记忆方法,如果能加上情绪、味觉、触觉的印象就记的更牢了,这可能和人类历史也有关系,有文字才几千年,没文字的几百万年呢。没文字的时候只能靠 图形、图案来记忆了。
下面,从3点说明线程池工作原理
线程池的接口定义和继承关系
线程池中线程的状态描述
线程池工作细节
因为不能粘贴源码,我会用思维导图的形式把上面几个点串起来。
1、线程池的接口定义和继承关系
上图可以看出线程池有哪些接口和类。最外面的接口是Executors,里面只有个一个方法是execute
, 然后是AbstractExecutorService,可以说是用了模版设计模式,线程的执行操作里面都有。
我们看一个比较不常用的方法,AbstractExecutorService.invokeAny(你可以直接使用额), 参数有tasks,time,timeUnit。干什么用的呢,场景就是有一批任务,等待一个task执行完才返回Futures,这个时候get()不会阻塞了。看了这个方法的源码 其实就是使用了ExecutorCompletionService帮你实现了,这个类poll操作可以返回最新执行完的Future,想想之前真傻逼,jdk已经提供了这个方法, 直接拿来用就可以了,这也印证了看源码真的可以提效,某些场景已经有相关的实现了。
上面的思维导图,我们再看右边的部分,创建线程池源码中出现两种不一样的构造方法。大部分我们还是用 ThreadPoolExecutor这个类的构造方法,但是也有几个方法,比如newSingle*
系列的。
那他们的差别在什么地方,看了源码发现FinalizableDelegatedExecutorService里面就多了一个方法,重写了 finalize(),这里面就是调用shutdown关闭线程池,那很好理解了就是线程池可以自己销毁。非单例的线程池可以这样玩,释放线程池资源。
这里衍生一个面试题:newSingleThreadExecutor(1)
和 newFixedThreadPool(1)
有什么区别?
答案是newSingleThreadExecutor里面委托掉了ThreadPoolExecutor这个类,只提供线程执行的方法,像 修改线程数、暂停线程等方法都去掉了,其实就是起到一种保护线程配置的作用,开闭原则的一个体现吧。
写到这里有点困了,快晚上11点了,
以上是关于线程池源码浅析的主要内容,如果未能解决你的问题,请参考以下文章
Java 线程池 ThreadPoolExecutor 八种拒绝策略浅析
newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段