20.核心线程池的内部实现

核心的几个线程池内部都是使用ThreadPoolExecutor实现的。

public static ExecutorService newFixedThreadPool(int nThreads){
    return new ThreadPoolExecutor(nThreads,
                                  nThreads,
                                  OL,
                                  TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

public static ExecutorService newSingleThreadExecutor(){
    return new FinalizableDelegatedExecutorService(
       new ThreadPoolExecutor(1,
                              1,
                              OL,
                              TimeUnit.MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>()));
}

public static ExecutorService newCachedThreadPool(){ 
    return new ThreadPoolExecutor(0, 
                                  Integer.MAX_VALUE, 
                                  60L, 
                                  TimeUnit.SECONDS, 
                                  new SynchronousQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize,     //指定线程池中的线程数量
                          int maximumPoolSize,  //指定线程池中最大的线程数量
                          long keeepAliveTime,  //当线程数量超过了corePoolSize,多余的空闲线程的存活时间
                          TimeUnit unit,        //keepAliveTime的时间
                          BlockingQueue<Runnable> workQueue, //任务队列,被提交但尚未被执行的任务
                          ThreadFactory threadFactory,       //线程工厂,用于创建线程,一般默认即可
                          RejectedExecutionHandler handler)  //拒绝策略,当任务太多来不及处理,如何拒绝服务

       workQueue指被提交但未执行的任务队列,它是一个BlockingQueue接口的对象,仅用于存放Runnable对象。

       ThreadPoolExecutor的构造函数可以使用以下几种BlockingQueue。

       直接提交的队列:SynchronousQueue。没有容量,总是将新任务提交给线程执行,即一提交任务就马上尝试要执行。如果没有空闲的线程,则尝试创建新的线程。如果线程数量已经达到了最大值,,则执行拒绝策略。

       因此,通常要设置很大的maximumPoolSize值,否则很容易执行拒绝策略。

       有界的任务队列:ArrayBlockingQueue。它的构造函数必须带一个容量参数,表示该队列的最大容量。

public ArrayBlockingQueue(int capacity)

       当有新的任务需要执行,如果线程池的实际线程数小于corePoolSize,则会优先创建线程,若大于corePoolSize,则会将新任务加入等待队列。若队列已满,无法加入,则在总线程数不大于maximumPoolSize的前提下,创建新的线程执行任务。
       若大于maximumPoolSzie,则执行拒绝策略。

      有界队列仅当在任务队列装满时,才可能将线程数提高到corePoolSize以上。除非系统繁忙,否则确保核心线程数维持在corePoolSzie。

       无界任务队列:LinkedBlockingQueue。与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。

     当有新的任务到来时,系统的线程数目小于corePoolSzie时,线程池就会生成新的线程执行任务,但线程数达到corePoolSzie后,就不会继续增加。

       若后续仍有新的任务加入,而无空闲的线程时,则任务加入队列。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直至耗尽系统内存。

      优先任务队列:PriorityBlockingQueue。是一个特殊的无界队列。之前的队列都是按照先进先出的原则进行的。而PriorityBlockingQueue总是确保高优先级的任务先执行。

       newFixedThreadPool(),返回一个corePoolSize和maximumPoolSzie大小一样,并且使用LinkedBlockingQueue的线程池。对于固定线程数目的线程池不存在线程数目的变化。使用无界队列存放无法立即执行的任务,当任务提交非常频繁的时候,该队列可以迅速膨胀,从而耗尽系统资源。

       newSingleThreadExecutor()是newFixedThreadPool()的退化版本。只是把线程数量设置为1。

       newCachedThreadPool()返回的corePoolSize为0,maximumPoolSize无穷大。没有任务的时候,该线程池内线程,当任务被提交的时候,该线程池会使用空闲线程执行任务,没有空闲线程则提交给SynchronousQueue队列,而SynchronousQueue队列是直接提交的队列,它会是线程池创建新的线程执行任务。

       当任务执行完毕,由于corePoolSzie为0,因此空闲线程会在指定时间(60s)内被回收。

//下面是ThreadPoolExecutor的核心实现
public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        int c = ctl.get();
        //workerCountOf()取得当前线程池的线程总数
        //当小于corePoolSize,调用addWorker
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //addWorker():进入队列失败,将任务直接提交给线程池
        else if (!addWorker(command, false))
            reject(command);  //如果当前线程数已经达到maximumPoolSize,就执行拒绝策略
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值