线程池总结

1.概览


功能简介:

  • ThreadPoolExecutor就是普通的线程池。
  • ScheduledThreadPoolExecutor特别适用于延迟执行任务:以固定间隔调度任务或者以固定延迟调度任务
  • ForkJoinPool适用于使用分治法(Divide-and-Conquer Algorithm)能够解决的问题,特点是工作密取。

2.线程池ThreadPoolExecutor的架构

2.1 线程池四大构件

  • 首先就是线程池本身:ctl状态管理、执行任务execute及submit、线程增加和缩减、以及shutdown和shutdownNow操作
  • 线程本身Worker,本身实现了AQS,在执行任务加锁,屏蔽了中断
  • 阻塞队列,从队列中取任务getTask
  • 任务FutureTask

2.2 任务两级调度模型

2.3 Executor框架的三大部分

  • 1.任务——Runnable Callable
  • 2.任务的执行——ThreadPoolExecutor、ScheduledThreadPoolExecutor
  • 3.异步计算的结果——Future(FutureTask)


3.ScheduledThreadPoolExecutor

3.1 Leader-Follower模式

参考并发容器BlockingQueue - DelayQueue及Leader-Follower模式
leader是等待队列头部元素的指定线程。Leader-Follower模式的这种变体用于最小化不必要的定时等待。

  • 当一个线程称为leader时,其会定时等待下一个delay元素过期,但是其他线程会无限期等待。
  • 当从take/poll返回之前,leader线程必须signal其他等待线程,除非在此期间有线程称为了新的leader。
  • 每当队列头部元素被更早到期的元素替换时,leader被置为null,offer里面q.peek() == e时,会将leader=null,此时当然会signal,重新竞选leader。所以定时等待线程必须要处理失去leader时情况。

3.2 ScheduledThreadPoolExecutor四大构件

  • 首先就是线程池本身:执行任务execute及submit被覆盖了以实现周期任务,增加了run-after-shutdown参数来处理线程池关闭后怎么处理周期任务
  • 线程还是沿用Worker,本身实现了AQS,在执行任务加锁,屏蔽了中断
  • 阻塞队列使用的是定制的DelayedWorkQueue,优先队列,ScheduledFutureTask会记录其在堆数组中索引,这会消除在取消时查找任务的操作,大大加快了移除操作。但是在siftUp和siftDown中会增加维护索引的额外操作。
  • 任务是继承自FutureTask的ScheduledFutureTask,实现了compareTo(基于time和序列号),方便放入DelayedWorkQueue。通过period区分是一次性任务还是周期性任务。通过setNextRuntime区分是scheduleAtFixedRate还是scheduleWithFixedDelay。

4.ForkJoinPool

4.1 四大构件

  • 线程池ForkJoinPool,核心的ctl打包了AC、TC、SS和ID,runState用于操作workQueues数组。

  • 工作线程ForkJoinWorkerThread,每个工作线程都会注册一个自己的WorkQueue,该WorkQueue放在workQueues数组奇数索引处。线程执行时,不一定会执行当前 WorkQueue 中的任务,而是可以偷取别的Worker的任务来执行。

  • 队列WorkQueue,支持工作窃取和外部任务提交的双端队列,只支持四种可能的端操作中的三种 - push,pop和poll(也称为steal),进一步的限制是push和pop仅从拥有的线程调用,而poll可以从其他线程调用。


  • 任务ForkJoinTask。
    1)任务类型
    RecursiveAction——不返回结果的计算
    RecursiveTask——返回结果
    CountedCompleter——已完成的操作触发其他操作
    2)内部提交
    fork——直接加入到当前线程的workQueue中
    invoke——提交任务等待任务完成并获取结果(当前线程执行)
    join——等待任务完成并获取结果,尝试在当前线程中开始执行。
    3)任务状态
    当状态完成时,为负数,表示正常完成、取消或者异常;
    阻塞等待的任务设置了SIGNAL

4.2 整体的运行机理

  • ForkJoinPool适合分治算法


  • 任务提交分为外部和内部提交



  • 整体运行图


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容