(三)JDK线程池源码分析2之线程生命周期

  • 概述
    JDK线程池源码分析1中我已经将线程池的创建,线程池中线程的创建,线程执行任务的整个流程已经分析完毕了,这次主要是来分析单个线程在线程池中是如何工作的以及如何被管理的.其实这个实现的流程主要在ThreadPoolExecutor的runWorker方法中进行实现的,对于runWorker是怎么触发的可以参考我的上一篇文章.

  • runWorker方法主流程
    在这里插入图片描述
    主要由三部分组成:
    a.获取任务.如果是刚加入的线程可能存在firstTask,那么执行创建线程分配的任务,如果不是刚加入的线程,那么将会去任务队列里面获取任务.
    b.执行任务
    3.工作线程退出.工作线程任务都执行完毕或者执行当中抛出异常,那么将这个线程进行处理

  • getTask方法主流程
    在这里插入图片描述
    主要分为两部分:
    1.判断当前线程是否要退出,这里分为很多中情况
    a.第一个if判断当前线程池的状态是不是SHUTDOWN(关闭)状态,因为线程池关闭状态意味着只是拒绝接收任务,但很有可能还有线程在执行任务,或者当前任务队列还有任务需要执行,如果任务队列已经没任务了,或者线程池的线程已经不活跃了,那么当前线程就再也不需要了,那么就可以关闭了,return null (调用的上层退出了while循环了,开始执行processWorkerExit)
    b.第二个if 假设我们让核心线程没有设置超时时间,即核心线程的个数一直存在allowCoreThreadTimeOut默认值false,如果在线程池只有核心线程池个数的时候,第二个if永远为false, 也就是在没有设置核心线程数量的线程的超时时间,线程池中永远都有核心个数线程.
    c.第二个if 假设我们让核心线程没有设置超时时间,即核心线程的个数一直存在allowCoreThreadTimeOut默认值false,如果当前线程数已经超过了核心线程数,那么timed=true,并且timeOut=true(当前线程上次获取任务就超时),并且当前任务队列还没任务可执行,那么说明当前线程处于闲置状态有段时间了,可以退出了.
    d.第二个if 假设我们让核心线程有设置超时时间,即allowCoreThreadTimeOut==true,这个时候只要有超时记录,并且当前任务队列还是没任务,那么即使是核心线程也是需要在闲置的情况下退出.
    e.第二个if 假设我们原来觉得maximumPoolSize太大了,这个时候我们动态调整了这个参数,那么会将线程池线程数量降到新的maximumPoolSize,然后后面还要不要退出更多的线程,会走上面的b,c,d策略
    2.经过上面判断,这个线程还是需要的,那么将直接获取任务,并且返回任务给上层,这里有两个方法去获取任务,分别是poll带阻塞时间,take一直阻塞
    a.如果没有设置核心线程的超时时间,那么直接执行token,不会返回null,也就没有核心线程超时说法,就不会记录有超时的标记
    b.如果设置了核心线程的超时时间,那么执行poll,如果在keepAliveTime的时间还没拿到任务,那么将标记为当前线程有超时的标记,那么再下一回将有可能退出当前线程.

  • processWorkerExit方法主流程
    在这里插入图片描述
    主要分为三个组成部分
    1.将不再需要(空闲或者执行任务抛出异常)的线程从线程池中移除
    2.尝试终止这个不需要(空闲或者执行任务抛出异常)的线程
    3.主要分为线程两种状态的处理:
    a.completedAbruptly=false算正常退出,所以只要保证核心线程数量就可以了,在getTask方法我已经分析过线程池保存核心线程数量的策略了
    b.completedAbruptly=true表示是非正常退出,是执行任务抛出异常导致退出的,这个时候其实是需要这个线程的,那么采用的策略直接是添加一个线程

  • 总结
    其实在上面几个方法中已经完整描述了线程池中线程的生命周期:
    1.allowCoreThreadTimeOut=false(不允许核心线程超时,核心线程一直存在)
    a.在核心线程够用的情况下,核心线程照常执行任务,核心线程一直阻塞,直到获取到队列的任务; 这种情况下核心线程只有两种情况会退出 1.线程池关闭 2.执行任务发生异常;在核心线程退出后的处理中也分两种情况,1.如果线程池处于停止状态,那么不处理;2如果线程池还是活跃状态,那么创建一个新的核心线程代替
    b.如果核心线程不够用,那么非核心线程是有超时时间的,那就是keepAliveTime这个参数,默认是0;如果非核心线程超时,那么将直接退出这个线程.所以keepAliveTime这个参数非常重要,设置不好会频繁删除/添加非核心线程
    2.allowCoreThreadTimeOut=true(允许核心线程超时)
    在这种情况下,核心线程和非核心线程其实生命周期是一样的,keepAliveTime这个参数对所有参数起效果,如果一超时,那么线程就直接退出,在退出的处理中,也是一样的,这个时候线程池的最小数量是可以为0的.闲置没有任务的话,所有线程都会退出.

发布了65 篇原创文章 · 获赞 11 · 访问量 7142

猜你喜欢

转载自blog.csdn.net/weixin_38312719/article/details/102598335