深入理解线程池的构造方法以及底层工作原理

    /**
     *
     * @param corePoolSize 线程池的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePollSize;
     *                     如果当前线程数为corePoolSize,继续提交的任务会被保存到阻塞队列中,等待被执行;
     *                     如果执行了线程池的prestartAllCoreThread()方法时,线程池会提前创建并启动所有的核心线程
     * @param maximumPoolSize 线程池中允许的最大线程数,如果阻塞队列满了,且继续提交任务,则会创建新的线程执行任务,
     *                        前提时当前线程数小于maximumPollSize;
     * @param keepAliveTime 线程池维护线程所允许的空闲时间,当线程池中的线程数量大于corePollSize时,如果这个时候没有新的任务提交,
     *                      核心线程外的线程不会立即销毁,而是会等待,直到等待时间超过的keepAliveTime;
     * @param unit keepAliveTime的单位
     * @param workQueue 用来保存等待被执行的任务的阻塞队列,且任务必须实现Runable接口,再jdk中提供了如下的阻塞队列:
     *                      1. ArrayBlockingQueue: 基于数组结构的有界阻塞队列,按FIFO排序任务
     *                      2. LinkedBlockingQueue: 基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQueue
     *                      3. SynchronousQueue: 一个不储存元素的阻塞队列,每个操作必须等到另一个线程调用移除操作,
     *                      否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue
     *                      4. priorityBlockingQueue: 具有优先级的无界阻塞队列
     * @param threadFactory 它是ThreadFactory类型的变量,用来创建新线程,默认调用Executors.defaultThreadFactory()来创建线程,使用默认的
     *                      ThreadFactory来创建线程时,会使新创建的线程具有先攻的NORM_PRIORITY优先级并且是非守护线程,同时也设置了线程的名称
     * @param handler   线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略
     *                      1.AbortPolicy: 直接抛出异常,默认策略
     *                      2.CallerRunsPolicy: 用调用者所在的线程来执行任务
     *                      3.DiscardOldestPolicy: 丢弃阻塞队列种最靠前的任务,并执行当前任务
     *                      4.DiscardPolicy: 直接丢弃策略
     *                  以上的4种策略都是ThreadPollExecutor的内部类
     *                  当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化储存不能处理的任务
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
    
    
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

线程池内部是通过队列+线程实现的,当我们利用线程池执行任务时:

  1. 如果此时线程池中的线程数量小于corePoolSize,即使线程池种的线程都处于空闲状态,也要创建新的线程来处理被添加的任务
  2. 如果此时线程池中的线程数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列
  3. 如果此时线程池中的线程数量大于等于corePoolSize,缓冲队列已满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务
  4. 如果此时线程池中的线程数量大于corePoolSize,缓冲队列已满,并且线程池中的数量等于maximumPoolSize,那么通过handler所指定的策略来处理此任务
  5. 当线程池中的线程数量大于corePollSize,如果某线程空闲时间超过keepAliveTime,线程将被终止,这样线程池可以动态调整池中的线程数

猜你喜欢

转载自blog.csdn.net/qq_43135259/article/details/120252271