一些静态变量的含义
// -536870912
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
/*
1->0000 0000 0000 0000 0000 0000 0000 0001
左移29位
->0010 0000 0000 0000 0000 0000 0000 0000
=线程池容量:1 * 2的29次方 - 1
536870911
*/
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
/*
-1->1000 0000 0000 0000 0000 0000 0000 0001
补码:1111 1111 1111 1111 1111 1111 1111 1111
左移29位
->1110 0000 0000 0000 0000 0000 0000 0000
原码:1001 0000 0000 0000 0000 0000 0000 0000
补码:1110 0000 0000 0000 0000 0000 0000 0000
-536870912
运行状态
*/
private static final int RUNNING = -1 << COUNT_BITS;
/*
0->0000 0000 0000 0000 0000 0000 0000 0000
关闭状态,拒绝添加任务,任务队列中的人物还可继续执行
*/
private static final int SHUTDOWN = 0 << COUNT_BITS;
// 停止状态,拒绝添加任务,抛弃任务队列中的任务,中断正在执行的任务
private static final int STOP = 1 << COUNT_BITS;
// 清空状态,没有任务执行和等待
private static final int TIDYING = 2 << COUNT_BITS;
// 终止状态
private static final int TERMINATED = 3 << COUNT_BITS;
构造方法
ThreadPoolExecutor
- ThreadPoolExecutor:有多个重载构造器,区别在于参数个数不同,最终都是执行下面的构造方法
- 参数介绍:
1、corePoolSize:核心线程数,核心线程默认是无超时时间,但可通过allowsCoreThreadTimeOut(boolean value)
设置核心线程是否可超时
2、maximumPoolSize:最大线程数,包括核心+非核心线程,当队列满载时,才会创建非核心线程来零时处理任务,如果corePoolSize = maximumPoolSize,则表示只有核心线程数
3、keepAliveTime:线程的超时时长
4、unit:超时时长的单位
5、workQueue:任务队列
6、threadFactory:线程工厂,默认是DefaultThreadFactory
7、handler:拒绝策略,当线程数达到最大线程数时,且任务队列满载时,会执行拒绝策略,默认是AbortPolicy,还有CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy以及自定义拒绝策略
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;
}
Worker
- Worker:本身就是一个Runnable对象,其构造方法中通过线程工厂创建一个线程,并添加runnable
private final class Worker extends AbstractQueuedSynchronizer
implements Runnable
{
...
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
...
}
核心API
- execute:添加任务到线程池中,先校验执行任务数量是否超过核心线程,
1、如果没有就将runnable包装到Worker中,开启线程去执行Worker中的runWorker()
2、 如果线程创建、开启失败、超过了核心线程数,就检查线程池的状态是running,将runnable添加到任务队列wokerQueue的任务队列中,等待被执行
3、如果线程池不是运行状态,就执行拒绝策略public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); // 核心1:工作线程未超过核心线程就直接创建新线程处理 if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } // 核心2:超过核心线程数,任务添加到任务队列中,等待空闲线程执行 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); } // 核心3:当任务队列满了,且没有超过最大线程数,就创建一个线程进行处理,如果失败则走拒绝策略 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); // 校验线程池状态,且特定条件校验任务队列为null if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { int wc = workerCountOf(c); // 校验线程数量是否达上限 if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; } } ... try { // 核心1:创建线程及关联任务 w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { // 核心2:线程池中实现线程安全是使用Lock锁,而并非synchronized同步机制 final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); workers.add(w); int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { // 开启线程 t.start(); workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
- runWorker:要么执行创建线程时绑定的任务,要么就是从等待队列中获取,通过while循环来延续当前线程的存活时间,当未获取到任务时,将结束while循环,当前线程执行结束
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { // 核心1:获取线程绑定的任务/从任务队列中获取 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 { // 执行任务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 { // 线程结束后,清空worker对象 processWorkerExit(w, completedAbruptly); } }
- getTask:从任务队列中拿任务;根据线程是否有超时限制,分别通过workQueue.poll()和workQueue.take()获取任务,二者区别在于,poll()当超过等待时间则返回一个null,而take()则是一直等待,直到有内容可返回
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); // 此处就是判断当前线程是否是超时线程; // allowCoreThreadTimeOut:核心线程是否有超时 // 执行任务的线程数超过核心线程数,就默认当前的线程为非核心线程, // 这样当没有任务可执行时就结束当前线程,当剩下线程数小于等于核心线程,则均默认为核心线程 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; } } }
- shutDown:关闭线程池,所谓关闭,则是无法在继续添加新的任务;首先是更改线程池的状态为SHUTDOWN,其次中断未在执行任务的线程
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 更改线程池状态,保证在添加任务时,无法继续添加 advanceRunState(SHUTDOWN); // 中断空闲的线程,通过worker.unLock()未对线程上锁来判断是否为空闲 interruptIdleWorkers(); // 钩子函数,可在自定义线程池中监听关闭线程池 onShutdown(); } finally { mainLock.unlock(); } tryTerminate(); }
- shutDownNow:关闭线程池,并返回任务队列中为执行的任务;首先也是更改线程池的状态为STOP,其次中断所有的线程,包括正在执行任务的线程,最后再将为执行的任务队列的任务返回
public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 更改线程池状态 advanceRunState(STOP); // 中断所有线程,包括正在执行任务的线程 interruptWorkers(); // 返回任务队列中为执行的任务列表 tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }
考点1:shutDown和shutDownNow的区别?1、前者无返回值,后者返回任务队列中未执行的任务列表;2、对应的线程池状态不同;3、前者会保留正在执行及未执行的任务继续执行,后者是将所有线程全部关闭
考点2:当shutDown停止线程池,对于后面这行完毕的线程是如何进行处理的?在getTask()中,有根据线程池的状态且任务队列为空的时候,会返回null对象,而不是继续等待,这样当前线程就结束了
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 在这个特定的场景下,判断任务队列是否为null,来结束当前线程
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
...
}
拒绝策略
- AbortPolicy:当队列无法添加时,直接抛异常
public static class AbortPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
- DiscardPolicy:当队列无法添加任务时,啥也不处理
public static class DiscardPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }
- DiscardOlderPolicy:当队列无法添加任务时,如果线程池未关闭状态,则会移除队列头部的任务,然后将新任务添加进去
public static class DiscardOldestPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } } }
- CallerRunsPolicy:当队列无法添加任务时,如果线程池未关闭状态,直接在调用线程池的线程中运行runnable;风险点:需要注意的是,可能会在主线程中执行耗时任务
public static class CallerRunsPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } } }