前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java线程池---getTask方法解析

Java线程池---getTask方法解析

作者头像
None_Ling
发布2018-10-24 15:04:57
2.1K0
发布2018-10-24 15:04:57
举报
文章被收录于专栏:Android相关Android相关

/** * Performs blocking or timed wait for a task, depending on * current configuration settings, or returns null if this worker * must exit because of any of: * 1. There are more than maximumPoolSize workers (due to * a call to setMaximumPoolSize). * 2. The pool is stopped. * 3. The pool is shutdown and the queue is empty. * 4. This worker timed out waiting for a task, and timed-out * workers are subject to termination (that is, * {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) * both before and after the timed wait. * * @return task, or null if the worker must exit, in which case * workerCount is decremented */

为了获取一个Task执行一个阻塞或者有超时限制的等待,决定于当前的配置。或者返回空,如果这个Worker对象必须退出了,原因如下:

  1. 可能当前的Worker数超过了maximumPoolSize
  2. 当前的线程池处于STOP状态
  3. 当前的线程池处于SHUTDOWN状态并且队列为空
  4. 这个Worker等待Task超时了,并且超时的Worker会被终止,也就是会判断allowCoreThreadTimeOut||workerCount>corePoolSize 返回一个Task,如果返回空的话,那么说明worker必须退出,在这种情况下,Worker的总数会被减少。
代码语言:javascript
复制
 private Runnable getTask() {
 boolean timedOut = false; // Did the last poll() time out?
     retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        boolean timed;      // Are workers subject to culling?

        for (;;) {
            int wc = workerCountOf(c);
            timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if (wc <= maximumPoolSize && ! (timedOut && timed))
                break;
            if (compareAndDecrementWorkerCount(c))
                return null;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }

        try {
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}
  1. timeOut标志位,当获取到的Task为空的话,那么timeOut标志位被设置成true
  2. 进入自旋状态,判断当前的线程池状态是否为SHUTDOWN状态或者STOP状态,或者队列为空,如果满足的话,那么Worker总数减一,并且返回空
  3. timed标志位,标志着是否需要从队列中等待keepAliveTime时间获取,也就是说如果没有任务的话,可以等keepAliveTime时长,如果还没有任务的话,那么则返回null
  4. 进入自旋状态,如果设置了allowCoreThreadTimeOut,那么coreThread也会有超时时间的等待,否则的话,如果当前的WorkerCount大于corePoolSize的话,那么超过的这些线程都会有超时的限制
  5. 当WorkreCount小于maximumPoolSize并且没有超时的话,那么就会进入获取Task的阶段,否则则进入销毁Worker的步骤中,如果减少worker失败的话,那么就会重新进入循环,而如果当前状态和之前状态不一致的话,那么就重新回到retry的地方,重新判断状态
  6. 而在获取Task的时候,会判断timed,如果timed为true的话,那么就会从Queue中等到keepAliveTime的时长,如果时间段中有新的任务的话,那么就会返回,否则的话,直接从队列中获取。把获取到的task返回
  7. 如果获取到的runnable为空的话,那么把timedOut设置成true

Q&A

  1. rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())的理解 答:大于等于SHUTDOWN的状态只有:SHUTDOWN,STOP,TIDYING,TERMINATED,而大于等于STOP的状态有:STOP,TIDYING,TERMIATED,所以只有当处于SHUTDOWN状态的时候,才会去判断WorkQueue是否为空,其他状态(STOP,TIDYING,TERMIATED)的话,则不会判断任务队列是否为空。也就满足了之前3说的,只有当SHUTDOWN并且队列为空的时候,才会退出。
  2. wc <= maximumPoolSize && ! (timedOut && timed)条件成立的时候,跳出循环开始获取Task 答:wokrerCount只有小于等于maximumPoolSize才会允许给它分配任务执行,否则的话,相当于线程池已经超负荷了,而!(timedOut&&timed)的话,就是说明,只有当timedOut||timed为false的时候,也就是timedOut为false或者timed为false的话,才能获取Task。 而timedOut默认是false,只有在获取不到Task的时候,才会被置为true,而timed只有当allowCoreThreadTimeOut||wc>corePoolSize的时候才会为true,也就是说,如果之前没有尝试获取过Task或者之前获取Task失败,而这一次不再有keepAliveTimeout限制的时候(也就是只有当Worker总数少于CorePoolSize,并且allowCoreThreadTimeOut为false的时候),才会继续尝试获取。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.06.26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档