美丽的爪哇岛我爱编程

Java线程池如何维护线程对象

2018-05-27  本文已影响34人  begonia_rich

今天被这个问题整晕了,好好想了一下看了看源码才整清楚,看来以前还是没有理解的深入啊..稍微换个问法就晕了

线程池的基本流程

先弄清楚基本流程再去看部分实现细节

1如果运行的线程少于corePoolSize,则Executor始终首选添加新的线程,而不进行排队.
2如果运行的线程等于或多于corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程.
3如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝.

这个流程一定要记清楚,这是最基本的流程啦

基本流程实现

我以JDK1.8中execute方法看看大体编码实现过程(略去部分细节)

execute方法

可以看到execute方法就是对上面那三个流程的实现,这里就牵涉到另一个问题了,工作线程是如何工作的.下面继续看addWorker方法(这个方法太长了,我粘贴出来删去了部分)

addWorker方法

基本流程相当简单,将当前任务作为firstTask参数丢给Worker对象,然后维护Worker对象的引用,最后start起来Worker线程.

下面看一下如何维护Worker列表的,就是一个HashSet对象....


维护Worker的列表

下面看Worker对象的实现


Worker对象

看一下runWorker方法,这就是最后的核心逻辑了


runWorker

大体的代码实现细节就是这样的流程了.


总结

总结一下实现细节收获

1线程池如何维护线程对象?

直接通过HashSet持有,Worker对象是在addWorker方法后被新建一个Thread对象运行(Thread对象start之后并没有直接持有,这个Thread被放到了Worker对象作为一个属性持有了),Worker对象的run方法中自己会去自旋取阻塞队列中的Runnable任务.我们只维护了Worker对象,启动Worker对象的线程就在Worker对象中持有.停止时就是遍历了Worker对象取出线程对象,然后调用停止方法等...

2如果新增任务时并未达到核心线程池大小,那么新加入的任务是否有可能会被其他Worker线程执行?

不会,新任务不会进入阻塞队列并且新建Worker线程要求传入FirstTask任务参数,也就是Worker线程会先执行当前加入进来的第一个任务,然后再去阻塞队列获取任务执行.

3阻塞队列的阻塞如何实现的

基础的通知等待模型就可以实现.也可以用ReentrantLock和Condition实现(ArrayBlockingQueue和LinkedBlockingQueue都是基于这个实现的),线程池已不关心实现细节了,只要求是个阻塞队列就可以

其他

深入细节还是要去看一下源码,理解了细节才可以描述清楚线程池的实现,这里记录一下方便以后迷糊的时候回来理解...也希望能帮助到迷糊的同学....

上一篇 下一篇

猜你喜欢

热点阅读