今天来聊聊JAVA的线程池,然后联系上一点生活中的小常识,从而加深理解和记忆...

先上图:




java 线程池处理大数据文件入库 java线程池数据结构_任务队列

JAVA线程池



JAVA线程池结构很简单,有两个组件,一个是线程集合,一个是任务队列,线程集合里的线程不断地从队列里面获取任务来执行。为什么用这样的结构,早期的时候我们用一个 new Thread也能实现多线程。核心线程加任务队列的方案,能够消除多线程的资源消耗和线程安全问题。两者在源码里的实现一个是HashSet,一个是BlockingQueue。




java 线程池处理大数据文件入库 java线程池数据结构_线程池_02

线程集合




java 线程池处理大数据文件入库 java线程池数据结构_java队列_03

任务队列



再上代码:




java 线程池处理大数据文件入库 java线程池数据结构_java队列_04


用过的人都知道,这个是JAVA的线程池类构造函数,他的几个参数是理解的关键,首先让我们来看看源码中对他们的注释:

corePoolSize:线程池中的线程数,除非allowCoreThreadTimeOut=true,否则即使线程空闲也会存活在池子里

maximumPoolSize:池中允许的最大线程数 (这个理解要特别注意,且看下文分解)

keepAliveTime:当线程数大于核心时,空闲线程在终止之前等待新任务的最长时间

unit:keepAliveTime的时间单位

workQueue:队列,即上图的任务队列,保存任务用

handler:当达到了线程边界和队列容量,无法及时处理时,reject task使用的处理程序

对于corePoolSize和maximumPoolSize这两个参数,如下图所示:


java 线程池处理大数据文件入库 java线程池数据结构_java 线程池处理大数据文件入库_05

可扩展的线程集合


那么什么时候会去创建超过corePoolSize个的线程呢,我们会先入为主的认为当corePoolSize个线程处理不过来的时候,就会去创建额外的线程来处理任务,其实不然,且看下图:


java 线程池处理大数据文件入库 java线程池数据结构_java线程池_06

一个任务被拒绝的流程


我们看到,只有任务队列满的情况下,才会去扩展核心线程池,会创建大于corePoolsize小于maximumPoolSize个的线程去处理任务。通过这两个size可以实现灵活的线程池设计,上图黄色部分的线程就像是备用的线程,在任务过多,或是系统负载大的情况下,起到灵活扩展的作用。一般情况下,用核心线程池里的线程去处理任务就够了。这也许是corePoolsize和maximumPoolSize的设计初衷(理解有误请指正哦 ~_~)

有点要注意,在默认的情况下,corePoolsize个的线程(上图中的Thread1-3)始终是活着的,而大于corePoolsize小于maximumPoolSize个的那些线程(上图图中的Thread4-5),会在空闲一段时间(keepAliveTime)后退出。

各位对上述流程还不够理解的话,我们来点生活中的小常识。


java 线程池处理大数据文件入库 java线程池数据结构_线程池_07

一个外卖例子


不知道各位有没有理解了,觉得有用点个赞哦!