参考这篇https://blog.csdn.net/he90227/article/details/52576452,具体的源码实现太多,也容易乱,仅捋出来核心的思路在这里总结:
线程池的目的
我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?
在Java中可以通过线程池来达到这样的效果。
线程池如何工作
核心方法execute(Runnable runnable)
,意思是提交任务给线程池进行处理
对于上图的解释:
* 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
* 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列;
* 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还
是要创建非核心线程立刻运行这个任务;
* 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线
程池会抛出异常RejectExecutionException。
核心线程未满 = 正在运行的线程数
1)ArrayBlockingQueue:
基于数组的先进先出队列,此队列创建时必须指定大小;
2)LinkedBlockingQueue:基于链表的先进先出队列,
如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
3)synchronousQueue:这个队列比较特殊,它不会保存
提交的任务,而是将直接新建一个线程来执行新来的任务。
另外
注意两点
- 如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
- 如果线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime(这说明任务缓存队列为空呗),线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。
以上是基本上线程池维护的基本运行逻辑,具体细节还请看作文原文