/** * 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对象必须退出了,原因如下:
maximumPoolSize
STOP
状态SHUTDOWN
状态并且队列为空allowCoreThreadTimeOut||workerCount>corePoolSize
返回一个Task,如果返回空的话,那么说明worker必须退出,在这种情况下,Worker的总数会被减少。 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;
}
}
}
Q&A
rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())
的理解
答:大于等于SHUTDOWN的状态只有:SHUTDOWN,STOP,TIDYING,TERMINATED,而大于等于STOP的状态有:STOP,TIDYING,TERMIATED,所以只有当处于SHUTDOWN状态的时候,才会去判断WorkQueue是否为空,其他状态(STOP,TIDYING,TERMIATED)的话,则不会判断任务队列是否为空。也就满足了之前3说的,只有当SHUTDOWN并且队列为空的时候,才会退出。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的时候),才会继续尝试获取。