/ThreadPoolTree

线程池源码技术研究

Primary LanguageJava

ThreadPoolTree

线程池源码技术研究

常用的线程池类型:
      1)可缓存线程池 CachedThreadPool()
         1)线程数无限制
         2)有空闲线程则复用空闲线程,无空闲线程则新建线程。
        
      2)定长线程池FixedThreadPool()
         1)可控制线程最大并发数,同时执行的线程数
         2)超出的线程会在队列中等待。

      3)定时线程池ScheduledThreadPool()
         支持定时及周期性任务执行。

      5)单线程化的线程池SingleThreadExecutor()
         1)有且仅有一个工作线程执行任务;
         2)所有任务按照制定顺序执行,即遵循队列的入队出队规则。

线程池的状态

Running:
           创建线程池的时候,线程池的初始状态为Running,接着就可以进行提交任务执行了。

ShutDown:
           当在Running状态调用ShutDown()时,线程池的状态会被改为shutdown,这时候,submit任务
      会被拒绝。可以使用多种拒绝策略。

           对于正在执行中的线程,会继续执行,同时会把阻塞队列中的任务也一并执行完毕,等到全部任务
      执行完毕,线程池会进入Tidying状态,等执行钩子方法teriminated()之后,整个线程池完全终止。

Stop:
           当在Running状态调用ShutDownNow()时,线程池状态会被改为Stop(),这时候,submit任务会被拒绝,
      并中断各个工作线程,所以任务会如何执行要看任务做的是什么事情,有没有处理中断异常。而阻塞队列
      如果有任务,这些任务不会再执行,ShutDownNow()执行后,将会返回阻塞队列中的未执行的任务列表。

Tidying
           Tidying只是一个过渡状态,当所有工作线程都停止后,线程池的状态会进入Tidying状态,然后执行一个
      terminated()方法,最后线程池会进入Terminated状态。

Terminated
           线程池的终止状态。

ThreadPoolExcutor

workQueue: 阻塞队列
         ArrayBlockingQueue: 构造函数需要传大小,固定容量
         LinkedBlockingQueue: 构造函数不传大小时,默认为65535,容易造成内存耗尽。
         SynchronousQueue:同步队列,一个没有存储空间的阻塞队列,将任务同步交给工作线程
         PriorityBlockingQueue:优先级队列
         Distruptor:

Handler: 饱和策略
         AbortPolicy:默认, 直接抛弃
         CallerRunsPolicy:用调用者的线程执行任务。
         DiscardOldestPolicy:抛弃队列中最久的任务
         DiscardPolicy:抛弃当前任务


执行逻辑:
        1)当有任务提交的时候,会创建核心线程去执行任务(即使有核心线程空闲仍会创建);
        2)当核心线程数达到corePoolSize时,后续提交的都会进BlockingQueue中排队;
        3)当BlockingQueue满了(offer失败),就会创建临时线程(临时线程空闲超过一定时间后,会被销毁);
        5)当线程总数达到maximumPoolSize时,后续提交的任务都会被RejectedExecutionHandler拒绝

ThreadPoolExcutor继承关系

ThreadPoolExcutor代码逻辑

执行步骤:

      1)调用execute方法,传入Runable对象
      2)判断传入的对象是否为null,为null则抛出异常,不为null继续流程
      3)获取当前线程池的状态和线程个数变量
      5)判断当前线程数是否小于核心线程数,是走流程5,否则走流程6
      6)添加线程数,添加成功则结束,失败则重新获取当前线程池的状态和线程个数变量,
      7)判断线程池是否处于RUNNING状态,是则添加任务到阻塞队列,否则走流程10,添加任务成功则继续流程8
      8)重新获取当前线程池的状态和线程个数变量
      9)重新检查线程池状态,不是运行状态则移除之前添加的任务,有一个false走流程9,都为true则走流程12
      10)检查线程池线程数量是否为0,否则结束流程,是调用addWorker(null, false),然后结束
      11)调用!addWorker(command, false),为true走流程11,false则结束
      12)调用拒绝策略reject(command),结束