java线程的创建和销毁是要消耗资源的,Executor就是为了复用线程才设计的,ThreadPoolExecutor是Executor的典型实现,通过下图来简单概述一下ThreadPoolExecutor实现原理
- ThreadPoolExecutor有一个核心线程池和一个最大线程池,核心线程池内的线程不会因为取不到任务而销毁
- 提交任务时会先尝试添加核心线程,如果核心线程池没满就添加新的核心线程。不管创建过的核心线程有没有空闲,只要来了任务都会创建新的核心线程,直到核心线程数达到最大值
- 当核心线程达到最大值时,再提交任务就会将任务提交到阻塞队列中,阻塞队列有多种实现,java的Executors工具类提供了三种ThreadPoolExecutor的构造:使用LinkedBlockingQueue,核心线程和最大线程数一样的FixedThreadPool;使用LinkedBlockingQueue,核心线程和最大线程数都是1的SingleThreadExecutor;使用SynchronousQueue,核心线程是0、最大线程数都是integer最大值的CachedThreadPool
- 当阻塞队列已满,不能存放新的任务时,就会在最大线程池内创建会销毁的普通线程
- 不管是核心线程还是普通线程都会在创建后先执行创建时放入的任务,执行完后再从阻塞队列获取任务
- 当最大线程池也达到最大值时,会触发拒绝策略,拒绝策略可自定义,java提供的有:什么都不做、直接抛异常、阻塞队列抛弃第一个任务后将新任务再提交、由提交任务线程直接执行。
源码分析
1.属性
- ctl:存放了worker总数
- workQueue: 阻塞队列,存放任务
- workers:hashset存放worker
- largestPoolSize:当前线程池达到过的最大worker数
- completedTaskCount:线程池处理过的任务总数,只有在worker中断的时候才会将该worker处理的任务总数加入completedTaskCount
- threadFactory:用于产生worker的工厂类
- handler:拒绝策略,在线程池处理不了任务时调用
- keepAliveTime:worker的最大空闲时间,超过这个时间没取到任务会销毁worker
- allowCoreThreadTimeOut:是否允许核心线程超时,默认为false,可以调用allowCoreThreadTimeOut修改值
- corePoolSize:最大核心线程数
- maximumPoolSize:最大线程数,corePoolSize计算在内
- defaultHandler:默认的拒绝策略,抛出异常
- ONLY_ONE:boolean值,用于只中断一个worker
2.对外提供方法
Executor接口就一个方法executor,入参时一个Runnable的实现类,用于提交任务。ThreadPoolExecutor重写了executor方法。此外,ThreadPoolExecutor的继承了AbstractExecutorService类,AbstractExecutorService提供了可提交Callable任务的submit方法,submit将任务包装成一个FutureTask返回,调用方可根据返回值获取执行结果。
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
可以看到,提交的Callable任务最后会包装成RunnableFuture的实现类FutureTask返回给调用方,RunnableFuture继承了Callable和Runnable,所以可以使用Executor的executor方法提交FutureTask到线程池。
3.工作线程worker源码
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
private static final long serialVersionUID = 6138294804551838833L;
//线程对象,构造worker时将thread赋值为自己
//启动worker,就是通过这个thread调用自己的run方法
final Thread thread;
//第一个任务,也就是创建该工作线程时外部提交的任务
Runnable firstTask;
//worker处理完成的任务数
volatile long completedTasks;
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
//thread对象创建时,可以放入一个runnable,此处放的就是worker自己
this.thread = getThreadFactory().newThread(this);
}
public void run() {
//worker处理任务的核心代码
runWorker(this);
}
protected boolean isHeldExclusively() {
return getState() != 0;
}
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
protected boolean tryRelease(int unused) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
public void lock() { acquire(1); }
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); }
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
}
4.execute方法源码
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//如果工作线程数小于核心线程数最大值,则创建新的核心线程处理本次任务
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);
//如果线程数为0,则补充工作线程,添加的新工作线程不会处理本次任务,会直接从阻塞队列取
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//如果阻塞队列满了,则添加新的工作线程处理本次任务
else if (!addWorker(command, false))
//工作线程达到最大值则执行拒绝策略
reject(command);
}
addWorker方法:
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
//根据传入的boolean值core判断线程数超没超过限制
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//使用cas增加工作线程数,如果成功跳出循环,如果失败继续循环添加
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get();
if (runStateOf(c) != rs)
continue retry;
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//new一个新的worker,并将本次任务赋值给worker的firstTask属性
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive())
throw new IllegalThreadStateException();
//workers是一个hashset,将新的worker加入set
workers.add(w);
int s = workers.size();
//更新当前最大线程数
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//如果添加成果,则执行worker的run方法
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
worker的run方法调用了runWorker方法
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock();
boolean completedAbruptly = true;
try {
//while循环先判断worker的firstTask是否为空,firstTask为空时才从阻塞队列获取任务
//当getTask在没获取到任务时,会返回null跳过while循环
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,进入下一次while循环
task = null;
//增加本worker的处理任务数
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
//跳过while循环的就会将该工作线程销毁
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);
//判断当前worker能不能超时销毁
//allowCoreThreadTimeOut默认为false,设置为true代表核心线程也可以因为
//超过keepAliveTime没获取到任务而销毁
//如果worker总数大于核心线程数,说明该线程可以看做普通线程,可以销毁
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//如果当前工作线程大于最大线程数或已超时
//同时最大线程数大于1或阻塞队列内没有任务
//则返回null,调用方在返回null时可能销毁本worker
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;
}
}
}
processWorkerExit方法
private void processWorkerExit(Worker w, boolean completedAbruptly) {
//是否因为异常突然销毁本线程,如果是,则减少线程总数值
//如果不是则之前getTask操作已经减少过这个值了,不需要再减
if (completedAbruptly)
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//增加线程池总的处理量
completedTaskCount += w.completedTasks;
//将本worker从hashes中移除
workers.remove(w);
} finally {
mainLock.unlock();
}
//中断本线程
tryTerminate();
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
//如果allowCoreThreadTimeOut为true,相当于没有持久的核心线程
//如果此时worker数为0并且此时工作队列有任务,则补充一个线程
if (min == 0 && ! workQueue.isEmpty())
min = 1;
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null, false);
}
}
5.其他方法
getCompletedTaskCount获取线程池处理完的总任务数
public long getCompletedTaskCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//n为每个worker中断退出时加上来的任务数
long n = completedTaskCount;
//在循环加上每个存活的worker处理过的任务数
for (Worker w : workers)
n += w.completedTasks;
return n;
} finally {
mainLock.unlock();
}
}
getTaskCount获取线程池接收成功的总任务数
public long getTaskCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//n为每个worker中断退出时加上来的任务数
long n = completedTaskCount;
for (Worker w : workers) {
//在循环加上每个存活的worker处理过的任务数
n += w.completedTasks;
//如果worker被锁住了,说明正在处理任务,加上这个还没处理完的任务
if (w.isLocked())
++n;
}
//再加上阻塞队列内还没处理的任务数
return n + workQueue.size();
} finally {
mainLock.unlock();
}
}
getActiveCount获取当前处于活动状态的worker数
public int getActiveCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
int n = 0;
for (Worker w : workers)
//如果worker被锁住了,说明该worker正在处理任务,总数加1
if (w.isLocked())
++n;
return n;
} finally {
mainLock.unlock();
}
}
prestartAllCoreThreads提前预热,将核心线程都提前创建好
public int prestartAllCoreThreads() {
int n = 0;
while (addWorker(null, true))
++n;
return n;
}
添加一个核心线程
public boolean prestartCoreThread() {
return workerCountOf(ctl.get()) < corePoolSize &&
addWorker(null, true);
}
添加一个worker
void ensurePrestart() {
int wc = workerCountOf(ctl.get());
if (wc < corePoolSize)
addWorker(null, true);
else if (wc == 0)
addWorker(null, false);
}