发表文章

[最新] 线程池ThreadPoolExecutor源码

liangwenmail 1月前 0

核心方法:


COUNT_BITS  29
CAPACITY    000 1111111111111111111111111111111  2的29次幂-1


RUNNING     111 0000000000000000000000000000000   
SHUTDOWN    000 0000000000000000000000000000000
STOP        001 0000000000000000000000000000000
TIDYING     010 0000000000000000000000000000000
TERMINATED  011 0000000000000000000000000000000


runStateOf 取出运行状态 高3位
workerCountOf 取出工作线程数量 低29位

ctlOf 把运行状态和工作线程放在同一个int里


构造
corePoolSize核心池大小:线程池里的线程小于它时候创建线程,当超过他时候把任务放到任务队列里,当任务队列满了的时候会线程的数量超过他。
maximumPoolSize最大线程数,线程池线程的数量最多为这个值。
keepAliveTime空闲时间,线程在等待任务时候超过这么长时间,将会返回然后结束线程。默认情况下只有线程数超过核心池大小时候,才会用延时的poll获取任务,等待这么长时间,没任务返回null。当设置允许核心池线程超时时候,所有线程都使用延时poll获取任务。
unit空闲时间单位。
workQueue任务队列,当工作线程数超过核心池大小时候,把任务放在任务队列里面。
threadFactory线程工厂,产生工作线程。
handler拒绝处理策略,丢弃任务,抛出异常,由提交任务的线程处理等。在任务队列已经满了或者线程池关闭的时候提交任务,会调用拒绝处理策略。



addWorker 用来新增一个线程,并启动线程。如果满足(1 STOP TIDYING TERMINATED;2在SHUTDOWN状态首个任务非空;3SHUTDOWN状态首个任务为空,工作队列也是空的)这三种情况之一,不会创建线程。如果当前线程数量大于线程池极限容量或者核心池容量或者线程池最大容量 也不会创建线程,而是直接返回。对工作线程数原子性加1,创建工作线程Worker,执行一个原子性操作:检查线程池状态,当运行状态是RUNNING 或者 运行状态是SHUTDOWN但是首个任务是NULL时候 保存工作线程,更新增加线程的标记,释放锁,根据标记启动工作线程里的线程。如果启动失败,对工作线程数原子性减1,移除工作线程。


Worker  它是一个任务,构造器初始化首个任务,使用线程工厂为首个任务创建线程。线程启动后,调用runWorker运行任务。


runWorker 运行任务,获取当前线程,获取首个任务,如果首个任务为空,不断在任务队列获取任务来执行,执行过程:先获取工作线程Worker的锁,如果状态是Stop tidying terminatated 则确保线程是中断状态,如果是running shutdown确保是非中断状态。调用任务的run方法运行任务,前后预留了接口可以自定义操作,运行完会对工作线程Worker的执行任务数+1,所有任务队列中任务处理完后,执行退出操作。


getTask() 获取任务,在一些情况下获取不到任务:1 stop tidying terminated三种状态, 2 shutdown状态 任务队列已经空了,3 工作线程数大于线程池的最大线程数且大于1或者任务队列已经空了 , 4 允许核心池的线程超时或者线程数量大于核心池的数量且任务队列中取出任务超时且工作线程数目大于1或任务队列已经空了。这几种情况下会对工作线程数原子性减1,返回null.校验后任务队列取出任务返回。


processWorkerExit 工作线程退出操作,如果线程意外结束,多一个原子减少当前工作线程数的操作。在工作线程集合移除工作线程,尝试停止线程池。当状态是running或shutdown时候,如果线程正常结束,维护一个线程最小值,当不允许核心池超时时候最小值是核心池大小,允许时候如果任务队列非空为1否则为0,当工作线程数不小于这个最小值时候直接返回,否则创调用addworker。


addWorkerFailed 工作线程添加失败,会在工作线程容器移除工作线程,减少工作线程数目,尝试停止线程池。


tryTerminate 尝试终止,在移除Worker时候会调用。当状态不是STOP或SHUTDOWN且任务队列为空时候直接返回,满足以上2个状态继续执行,如果工作线程数不是0则中断1个线程,并返回。如果工作线程数为0则更新状态为TIDYING,调用钩子方法,更新线程池状态为TERMINATED。


interruptIdleWorkers 中断空闲线程,遍历工作线程Worker集合,对worker里的线程中断,可以根据参数设置只中断1个或全部。


execute 执行任务,如果任务为空则抛出异常。如果工作线程数小于核心池大小,创建线程执行任务,成功后返回。如果超过核心池大小,如果是运行中则把任务放到任务队列,否则尝试创建线程执行任务,失败后拒绝处理。放到任务队列后,再次判断如果不是运行中,则在任务队列移除任务,拒绝处理任务。是运行中则,检查工作线程数为0创建一个没有任务的线程。


shutdown 关闭线程池 修改状态为shutdown,中断空闲线程,尝试停止线程池。


shutdownNow 关闭线程池 修改状态为stop,中断所有线程,返回等待执行的任务列表,尝试停止线程池。


线程池运行原理: 
execute提交任务:如果工作线程数目<核心池大小,则创建线程启动任务并返回。如果没有返回,判断如果线程池是运行中状态且任务存入任务队列成功,则再次检查线程池状态如果不是运行中则移除任务,拒绝处理任务,否则保证至少1个线程运行,然后在任务队列获取任务来执行。如果线程池不是运行中或任务添加到队列失败,则尝试创建1个线程启动任务,如果执行失败拒绝处理任务。
addWork创建线程启动任务:校验,如果状态是stop tidying或terminated校验不通过;如果状态是shutdown且首个人任务不为null校验不通过;如果状态是shutdown且首个任务为null且任务队列已经空了校验不通过;如果工作线程数大于线程池极限或者根据参数大于核心池或线程池最大值校验不通过。创建工作者线程,如果状态是运行中或者shutdown且首个任务为空,则保存工作者线程并启动线程运行任务,如果启动失败则做启动任务失败处理。
runWorker运行任务:如果首个任务不为空执行首个任务,为空不间断在任务队列获取任务来执行直到获取到的任务为空,如果线程池是stop tidying terminated确保中断,否则撤销中断,运行任务,当获取的任务为空或抛 出异常后,执行运行任务退出操作。
getTask获取任务:首先校验,如果当前是stop tidying terminated状态返回null,如果是shutdown状态且任务队列为空返回null。当设置了允许核心线程超时或工作线程数超过核心池大小,将使用限时的poll在任务队列获取任务,在等待构造器设置的最大空闲时间后获取不到任务返回null,否则将使用take在任务队列获取任务,获取不到任务会一直等待,直到有线程添加了任务。
processWorkerExit退出任务:移除工作线程,尝试终止线程池,如果线程池状态是运行中或shutdown,判断如果任务正常结束,会计算一个最小线程数,如果允许核心线程超时则为0否则为核心线程大小,如果是0若任务队列非空则为1,如果此时线程数大于最小线程数直接返回,最后创建一个首个任务为空的线程运行。
addWorkerFailed启动任务失败:移除工作线程,尝试终止线程池。
tryTerminate尝试终止线程池:首先校验状态,只允许shutdown且任务队列空或stop状态通过,其他状态直接返回;再校验如果工作线程数不是0直接则终止一个空闲线程并返回。通过2次校验后,把线程池状态更新为tidying,然后调用钩子方法terminated(),这是个空方法,我们可以自己实现,完成后,把线程池状态更新为terminated完成关闭。
shutdown关闭线程池:修改状态为shutdown,中断所有空闲线程,尝试终止线程池。

shutodwnNow关闭线程池:修改状态为stop,中断所有线程,尝试终止线程池。


相关推荐
最新评论 (0)
返回
发表文章
liangwenmail
文章数
382
评论数
0
注册排名
638115