新增线程的流程:
1、先判断新线程是不是为空,为空就报空指针错误否则就往下运行;
2、判断是否小于核心线程数,小于则直接新增线程否则就往下运行;
3、尝试新增到工作队列中,添加成功就等待调用否则就往下运行;
4、再次尝试新增非核心线程,如果当前线程池的线程数大于线程池容量或最大线程数就触发拒绝策略。
public void execute(Runnable command) {
//新任务为空则报空指针
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//worker指一个线程,这里是判断当前线程数是否小于核心线程数
if (workerCountOf(c) < corePoolSize) {
//当前线程数小于核心线程数就直接addWorker,即新增线程
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);
} //走到这说明线程队列已满,添加到工作队列失败,就再次尝试新增非核心线程(目的是为了判断是否大于最大线程数)
else if (!addWorker(command, false))
//添加失败触发拒绝策略
reject(command);
}
addWorker方法中新增线程时的判断:
//此处判断线程数如果大于等于容量或者大于等于最大线程数都返回false
if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
return false;
补充:线程池为什么能线程复用?
从上面的execute方法里面可以看到一个关键的对象:Worker,新增一个线程也是新增一个Worker:
点进去发现Worker是个继承AQS,实现Runnable的内部类,而且它的run方法又调用了ThreadPoolExecutor的runWorker方法:
runWorker方法:
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock();
boolean completedAbruptly = true;
try {
//线程复用的关键:当worker的线程不为空,或者工作队列中的线程不为空时,一直循环调用
while (task != null || (task = getTask()) != null) {
w.lock();
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x;
throw x;
} catch (Error x) {
thrown = x;
throw x;
} catch (Throwable x) {
thrown = x;
throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
getTask方法:
private Runnable getTask() {
boolean timedOut = false;
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
//判断运行状态
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
//判断线程数和是否超时
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//从工作队列中取线程
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}