if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
上面是源代码,首先说说poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)这句话说明如果线程数小于corePoolSize ,就会调用addIfUnderCorePoolSize(command),源码如下:
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (poolSize < corePoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
if (t == null)
return false;
t.start();
return true;
}
其实就是直接创建新线程执行任务。如果线程数大于或者等于corePoolSize 的话就先插入队列,如果插入队列成功,由于这些判断不是在lock锁里面判断的,所以插入成功之后再次检查runState状态和poolSize数量。如果runState != RUNNING || poolSize == 0则说明两种情况,两种情况的源码处理如下:
private void ensureQueuedTaskHandled(Runnable command) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
boolean reject = false;
Thread t = null;
try {
int state = runState;
if (state != RUNNING && workQueue.remove(command))
reject = true;
else if (state < STOP &&
poolSize < Math.max(corePoolSize, 1) &&
!workQueue.isEmpty())
t = addThread(null);
} finally {
mainLock.unlock();
}
if (reject)
reject(command);
else if (t != null)
t.start();
}
第一种情况是插入队列之后,runState状态已经不是running,这样的话,如果任务还在workQueue中,workQueue.remove(command)成功,拒绝执行command;一种是插入队列之后,runState为running,但是线程池没有存活的线程。这样的话,在保证 poolSize < Math.max(corePoolSize, 1) 以及workQueue不为空,需要新建一个新线程来执行完workQueue中的任务。有人肯定会问那如果runState是shutDown状态,然后workQueue中又没有command的情况,我觉得这种情况很少,就算出现了,也不会有问题,要使workQueue不存在command只有两种情况,一种是被getTask执行掉了,一种是shutDownNow把workQueue清空了,但是时间间隙这么少基本上不会出现,就算出现了,也会走第二种情况不会出现问题。
继续上面的讲解,如果poolSize >= corePoolSize而且 command又无法加入workQueue,这样的话会执行addIfUnderMaximumPoolSize,源码如下
private boolean addIfUnderMaximumPoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (poolSize < maximumPoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
if (t == null)
return false;
t.start();
return true;
}
上面的代码和addIfUnderCorePoolSize一模一样就是判断poolSize是否小于maximumPoolSize ,如果是,就新建线程执行command.否则就会调用 reject(command),拒绝任务。