【JUC源码】线程池:ThreadPoolExecutor(二)底层结构分析

港控/mmm° 2022-10-31 13:49 306阅读 0赞

线程池系列:

  • 【JUC源码】线程池:ThreadPoolExecutor(一)继承关系分析
  • 【JUC源码】线程池:ThreadPoolExecutor(二)底层结构分析
  • 【JUC源码】线程池:ThreadPoolExecutor(三)Worker 设计思路及源码分析
  • 【JUC源码】线程池:ThreadPoolExecutor(四) 任务执行流程源码分析
  • 【JUC源码】线程池:ThreadPoolExecutor(五)提炼总结
  • 【JUC源码】线程池:创建线程池的参数设置思路&Excutors
  • 【JUC源码】线程池:关于 ThreadPool 的几个问题

在文章开始之前,我们先要明白为啥要有线程池这么个东西。线程是一种稀缺资源,若不加以限制,不仅会占用大量资源,还会影响系统的稳定性。而线程池可以对线程的创建与停止、线程数量等等因素加以控制,使得线程在一种可控的范围内运行,在保证系统稳定运行的同时,还使得性能调优更加方便。另外,每次请求到来时,由于线程的创建已经完成,所以可以直接执行任务,减少了每次创建线程、销毁线程的开销,提高了响应速度。

OK,下面我们就进入正戏,源码…

ThreadPoolExecutor 核心继承关系,成员变量及主要构造函数:

  1. public class ThreadPoolExecutor extends AbstractExecutorService {
  2. // ctl 线程池状态控制字段,由两部分组成:
  3. // int ctlOf(int rs, int wc) { return rs | wc; }
  4. private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
  5. // 1:workerCount wc 工作线程数,我们限制 workerCount 最大到(2^29)-1,大概 5 亿个线程
  6. private static final int COUNT_BITS = Integer.SIZE - 3;// 29
  7. private static final int CAPACITY = (1 << COUNT_BITS) - 1;// =(2^29)-1=536870911
  8. // 2:runState rs 线程池的状态,提供了生命周期的控制,源码中有很多关于状态的校验,状态枚举如下:
  9. private static final int RUNNING = -1 << COUNT_BITS;//536870912
  10. private static final int SHUTDOWN = 0 << COUNT_BITS;//0
  11. private static final int STOP = 1 << COUNT_BITS;//536870912
  12. private static final int TIDYING = 2 << COUNT_BITS;//1073741824
  13. private static final int TERMINATED = 3 << COUNT_BITS;//1610612736
  14. // Worker 线程池中任务执行的最小单元
  15. private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
  16. ...}
  17. // 任务队列,阻塞队列,来保持线程的存活周期
  18. // 注:这里使用阻塞队列而不是普通容器,是为了worker在取任务时借助它的线程调度能力
  19. // 比如当线程池中的线程空闲下来了,它就会在队列的另一端等待外部线程投递任务
  20. // 这里注意,因为将外部线程的任务放入任务队列调用的是offer方法,所以入队时不会出现外部线程阻塞
  21. private final BlockingQueue<Runnable> workQueue;
  22. // 工作线程集合,包含线程池中所有的工作线程
  23. private final HashSet<Worker> workers = new HashSet<Worker>();
  24. // 锁,大多数情况下是控制对 workers 的访问权限(如将新worker加入)
  25. private final ReentrantLock mainLock = new ReentrantLock();
  26. private final Condition termination = mainLock.newCondition();
  27. // 已完成任务的计数
  28. volatile long completedTasks;
  29. // 线程池最大容量
  30. private int largestPoolSize;
  31. // 已经完成的任务数
  32. private long completedTaskCount;
  33. //-----------------------------用户可控属性(volatile)-----------------------------
  34. // 可以使用 threadFactory 创建 thread
  35. // 创建失败一般不抛出异常,只有在 OutOfMemoryError 时候才会
  36. private volatile ThreadFactory threadFactory;
  37. // 线程空闲的最大时间
  38. private volatile long keepAliveTime;
  39. // coreSize,allowCoreThreadTimeOut决定是否回收
  40. private volatile int corePoolSize;
  41. // maxSize,除核心线程外,空闲就会回收
  42. private volatile int maximumPoolSize;
  43. // 饱和或者运行中拒绝任务的 handler 处理类
  44. private volatile RejectedExecutionHandler handler;
  45. // 默认的拒绝策略
  46. private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
  47. // 设置 true 的话,核心线程空闲 keepAliveTime 时间后,也会被回收
  48. // 需要调用allowCoreThreadTimeOut方法进行设置,默认false
  49. private volatile boolean allowCoreThreadTimeOut;
  50. //-------------------------------构造函数----------------------------------------
  51. // 构造函数的作用就是设置上面的volatile变量们
  52. // 注:前五参数个必有,theadFactory与rejected可以没有
  53. public ThreadPoolExecutor(int corePoolSize,
  54. int maximumPoolSize,
  55. long keepAliveTime,
  56. TimeUnit unit,
  57. BlockingQueue<Runnable> workQueue,
  58. ThreadFactory threadFactory,
  59. RejectedExecutionHandler handler) {
  60. ...}
  61. }

这里把几个相关参数再说一下:

线程池状态

  • RUNNING:可以接收新任务,同时也可以处理阻塞队列里面的任务
  • SHUTDOWN:不可以接收新任务,但可以处理阻塞队列里面的任务
  • STOP:不可以接收新任务,也不处理阻塞队列里的任务,同时中断正处理的任务
  • TIDYING:属于过渡阶段,在这个状态表示所有任务已经结束,当前线程池无有效线程,并将调用terminal方法
  • TERMINALED:终止状态
    在这里插入图片描述

拒绝策略

  • AbortPolicy(默认):抛出异常
  • CallerRunsPolicy:不使用线程池,主线程来执行
  • DiscardPolicy:直接丢弃任务
  • DiscardOldestPolicy:丢弃队列中最老任务

发表评论

表情:
评论列表 (有 0 条评论,306人围观)

还没有评论,来说两句吧...

相关阅读