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

线程池系列:

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

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

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

public class ThreadPoolExecutor extends AbstractExecutorService {
    
    
    
    // ctl 线程池状态控制字段,由两部分组成:
    // int ctlOf(int rs, int wc) { return rs | wc; }
	private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    // 1:workerCount  wc 工作线程数,我们限制 workerCount 最大到(2^29)-1,大概 5 亿个线程
    private static final int COUNT_BITS = Integer.SIZE - 3;// 29
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;// =(2^29)-1=536870911
    // 2:runState rs 线程池的状态,提供了生命周期的控制,源码中有很多关于状态的校验,状态枚举如下:
    private static final int RUNNING    = -1 << COUNT_BITS;//536870912
    private static final int SHUTDOWN   =  0 << COUNT_BITS;//0
    private static final int STOP       =  1 << COUNT_BITS;//536870912
    private static final int TIDYING    =  2 << COUNT_BITS;//1073741824
    private static final int TERMINATED =  3 << COUNT_BITS;//1610612736

    
    // Worker 线程池中任务执行的最小单元
    private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
    
    ...}
    
    
    // 任务队列,阻塞队列,来保持线程的存活周期
    // 注:这里使用阻塞队列而不是普通容器,是为了worker在取任务时借助它的线程调度能力
    //    比如当线程池中的线程空闲下来了,它就会在队列的另一端等待外部线程投递任务
    //    这里注意,因为将外部线程的任务放入任务队列调用的是offer方法,所以入队时不会出现外部线程阻塞
    private final BlockingQueue<Runnable> workQueue;
	// 工作线程集合,包含线程池中所有的工作线程
    private final HashSet<Worker> workers = new HashSet<Worker>();
    // 锁,大多数情况下是控制对 workers 的访问权限(如将新worker加入)
    private final ReentrantLock mainLock = new ReentrantLock();
    private final Condition termination = mainLock.newCondition();
    
   
    // 已完成任务的计数
    volatile long completedTasks;
    // 线程池最大容量
    private int largestPoolSize;
    // 已经完成的任务数
    private long completedTaskCount;
    
    //-----------------------------用户可控属性(volatile)-----------------------------
    // 可以使用 threadFactory 创建 thread
    // 创建失败一般不抛出异常,只有在 OutOfMemoryError 时候才会
    private volatile ThreadFactory threadFactory;
    // 线程空闲的最大时间
    private volatile long keepAliveTime;
    // coreSize,allowCoreThreadTimeOut决定是否回收
    private volatile int corePoolSize;
    // maxSize,除核心线程外,空闲就会回收
    private volatile int maximumPoolSize;
    // 饱和或者运行中拒绝任务的 handler 处理类
    private volatile RejectedExecutionHandler handler;
    
    // 默认的拒绝策略
    private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
    
    // 设置 true 的话,核心线程空闲 keepAliveTime 时间后,也会被回收
    // 需要调用allowCoreThreadTimeOut方法进行设置,默认false
    private volatile boolean allowCoreThreadTimeOut;
    
    //-------------------------------构造函数----------------------------------------
    // 构造函数的作用就是设置上面的volatile变量们
    // 注:前五参数个必有,theadFactory与rejected可以没有
    public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    
    ...}
}

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

线程池状态

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

拒绝策略

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

猜你喜欢

转载自blog.csdn.net/weixin_43935927/article/details/113965321