线程池工作原理
线程池状态的切换:
线程池关键类的uml图:
线程池就是把任务提交和任务执行解耦。
首先看一下线程池的使用:
public static void main(String args[]) throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(10);//1,创建线程池
es.submit(()->{System.out.println("执行任务");});//2,提交任务
es.shutdown();//3,线程池关闭
}
跟进源码:
1,创建线程池:
(可以看出来只是对线程池对象ThreadPoolExecutor属性的赋值)
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
几个重要的参数:
基本大小,corePoolSize 基本的工作线程数。
最大大小 maximumPoolSize 当工作线程大于core,且workQueue也满了的情况下(arrayQueue),可以创建的最大工作线程。
保持存活时间 keepAliveTime 阻塞队列poll时的延时值,即如果线程在这个时间内仍然拿不到可以工作的任务,则杀死线程。
阻塞队列 workQueue 工作大于等于coreSize时用来阻塞的阻塞队列
线程工厂 threadFactory 生成新线程的工厂类
拒绝策略 rejectedExecutionHandler 线程池停止或者满了的时候的拒绝策略类
2,提交任务
提交任务的关键思路:
submit时如果状态合适,会创建执行线程,去执行任务。
或者是运行状态下,工作线程已经大于等于coreSize的线程,则会放入到阻塞队列,等待有空闲下来的线程来执行。
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);//创建一个 FutureTask
execute(ftask);//提交任务
return ftask;//返回future
}
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
//提交一个任务,如果工作线程数小于coreSize,则直接加入一个worker。加入失败则继续
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//二次检查,如果线程池是运行状态,则把command加入阻塞队列中。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//如果不是运行状态,从queue去除。
if (! isRunning(recheck) && remove(command))
reject(command);
//如果是运行,且没有工作线程,增加一个worker。
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//如果不能加入,则拒绝。(队列已满,尝试再加入,如果加入失败,则拒绝)
else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//判断是否状态不为running 并且 (状态不为SHUTDOWN || firstTask不为null || workQueue为空)
//如果满足,直接return。不做任何事情
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
//如果工作线程已经大于最大数量或者 大于core或max,则return。
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//cas增加工作线程数,增加成功跳出大循环
if (compareAndIncrementWorkerCount(c))
break retry;
//增加失败,继续判断状态,继续循环
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//创建新的Worker
w = new Worker(firstTask);
//线程工厂创建出一个有着传入任务firstTask的线程
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
//如果线程池为running或者为shutdown并且firstTask为null(关闭前提交任务)
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
//如果t已经启动,则抛出异常。
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//workers增加线程w
workers.add(w);
int s = workers.size();
//
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
//如果加入到workers,则启动。
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
//如果启动失败,没有调用start方法时,则原子操作减去workCount,从workers移除。
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
2.1 worker的执行
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
//获取worker里面的任务。
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//如果task为null时则去workqueue里去取任务,直到取完,则关闭这个工作线程。
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
//如果线程池正在关闭,确保线程被 interrupted,如果没有,确保线程没有被 interrupted,这个需要二次检查防止调用shutdownNow 时正在interrupt。
//判断如果状态已经是stop,或者 当前线程已经被打断并且线程状态已经是stop并且workers还没有被关闭。 调用interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
//模板方法,前置调用
beforeExecute(wt, task);
Throwable thrown = null;
try {
//调用run方法,执行任务。
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);
}
}
//
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
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;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//如果工作线程数已经大于最大数目并且 (工作线程数大于1或者工作队列为空),cas减去工作线程数,返回。
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//判断是否容许延时取出,如果allowCoreThreadTimeOut为真或者 工作线程数大于coreSize,则延时取出,否则一直等待取出。
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
//自旋等待r不为null的任务
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();//如果执行失败,则减去worker数目
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
//从workers中移除需要执行的任务w
workers.remove(w);
} finally {
mainLock.unlock();
}
如果执行完成时线程池正在关闭,工作线程数为0,则把线程池状态置为终止terminate
tryTerminate();
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
//正常执行完是false,则进入。
if (!completedAbruptly) {
//min为0或者coreSize。
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
//如果min为0且阻塞队列不为空。则min置为1。
if (min == 0 && ! workQueue.isEmpty())
min = 1;
如果工作线程数大于min,则不需要再增加工作线程,如果比min还小,则会走到下面的addWorker。
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null, false);
}
}
3,线程池关闭
shutdown的操作
1判断shutdown权限
2修改线程池状态,不再接受新任务
3interrupt所有线程
4修改状态到terminal
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//检查当前线程是否有能修改所有工作线程的权限
checkShutdownAccess();
//自旋 + cas 去修改线程池的状态。
advanceRunState(SHUTDOWN);
//尝试interrupt所有工作线程t.interrupt()
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
final void tryTerminate() {
//自旋,如果失败继续执行。
for (;;) {
int c = ctl.get();
//如果是running或者已经是tidying或者terminate,则不用做操作。
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//如果工作线程不为0,则尝试interrupt后返回。
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {//将状态置为tidying然后调用模板方法 terminated,之后将状态置为terminated。
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}