Worker执行任务的模型如下图所示:

图7 Worker执行任务
线程池需要管理线程的生命周期 , 需要在线程长时间不运行的时候进行回收 。线程池使用一张Hash表去持有线程的引用 , 这样可以通过添加引用、移除引用这样的操作来控制线程的生命周期 。这个时候重要的就是如何判断线程是否在运行 。
Worker是通过继承AQS , 使用AQS来实现独占锁这个功能 。没有使用可重入锁ReentrantLock , 而是使用AQS , 为的就是实现不可重入的特性去反应线程现在的执行状态 。
- lock方法一旦获取了独占锁 , 表示当前线程正在执行任务中 。
- 如果正在执行任务 , 则不应该中断线程 。
- 如果该线程现在不是独占锁的状态 , 也就是空闲的状态 , 说明它没有在处理任务 , 这时可以对该线程进行中断 。
- 线程池在执行shutdown方法或tryTerminate方法时会调用interruptIdleWorkers方法来中断空闲的线程 , interruptIdleWorkers方法会使用tryLock方法来判断线程池中的线程是否是空闲状态;如果线程是空闲状态则可以安全回收 。

图8 线程池回收过程
2.4.2 Worker线程增加
增加线程是通过线程池中的addWorker方法 , 该方法的功能就是增加一个线程 , 该方法不考虑线程池是在哪个阶段增加的该线程 , 这个分配线程的策略是在上个步骤完成的 , 该步骤仅仅完成增加线程 , 并使它运行 , 最后返回是否成功这个结果 。addWorker方法有两个参数:firstTask、core 。firstTask参数用于指定新增的线程执行的第一个任务 , 该参数可以为空;core参数为true表示在新增线程时会判断当前活动线程数是否少于corePoolSize , false表示新增线程前需要判断当前活动线程数是否少于maximumPoolSize , 其执行流程如下图所示:

图9 申请线程执行流程图
2.4.3 Worker线程回收
线程池中线程的销毁依赖JVM自动的回收 , 线程池做的工作是根据当前线程池的状态维护一定数量的线程引用 , 防止这部分线程被JVM回收 , 当线程池决定哪些线程需要回收时 , 只需要将其引用消除即可 。Worker被创建出来后 , 就会不断地进行轮询 , 然后获取任务去执行 , 核心线程可以无限等待获取任务 , 非核心线程要限时获取任务 。当Worker无法获取到任务 , 也就是获取的任务为空时 , 循环会结束 , Worker会主动消除自身在线程池内的引用 。
try{while(task!=null||(task=getTask())!=null){//执行任务}}finally{processWorkerExit(w,completedAbruptly);//获取不到任务时 , 主动回收自己}线程回收的工作是在processWorkerExit方法完成的 。
图10 线程销毁流程
事实上 , 在这个方法中 , 将线程引用移出线程池就已经结束了线程销毁的部分 。但由于引起线程销毁的可能性有很多 , 线程池还要判断是什么引发了这次销毁 , 是否要改变线程池的现阶段状态 , 是否要根据新状态 , 重新分配线程 。
推荐阅读
- cad卸载工具怎么用 cad卸载干净的教程
- qq营销工具源码 最有效推广的方式
- 目前三防手机哪个好 最好的三防手机品牌
- 哪些人不宜喝酒
- 艾灸真的可以治疗哮喘吗
- 面包硬的其他原因
- 钓鲈鱼的饵料比较好用的有哪些
- 黄皮果的食用方法
- 骨盆前倾该怎么练呢
- 骨盆前倾是怎么形成的呢
