ThreadPoolExecuor是JDK中默認線程池的實現。下面我們對其進入深入剖析。首先來一張類圖
其繼承關係還是很清晰明瞭的,下面從Executor說起,Executor 這個接口只是定義了一個方法executor(Runnable r),用於向線程池提交一個任務。注意到一點這個方法的返回值還是空的。
public interface Executor {
void execute(Runnable command);
}
ExecutorService 這個接口開始有了線程池的一些雛形,定義了一些線程池的基礎方法如(狀態相關,控制相關),其中比較重要的方法應該是submit(),並且會放回一個Future對象,用於獲取執行結果(是否執行完畢)。同時還允許提交一個Callable對象,結合Future對象使用,可以真實獲取執行的結果,彌補了Runable 對象執行完畢,無法獲得結果的缺陷。後面會對Future及Callable進行深入分析。
public interface ExecutorService extends Executor {
/**
* 關閉空閒的worker 線程,不會影響執行中的任務
*
*/
void shutdown();
/**
* 將所有執行中的線程置爲中斷,並返回未執行的任務
*/
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
/**
* 若爲停止狀態則直接返回,否則等待後再判斷返回
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/**
*
* 提交一個有返回結果的任務
*/
<T> Future<T> submit(Callable<T> task);
/**
* 提交一個Runnbale對象,以及一個結果
*/
<T> Future<T> submit(Runnable task, T result);
/**
* 不解釋
*/
Future<?> submit(Runnable task);
/**
* 批量執行
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
/**
*
* 給點的時間內批量執行
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 提交一堆任務。其中一個有返回結果就返回。
*
*/
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
/**
* 給定的時間範圍內,提交一堆任務,其中一個執行完且再時間範圍內就返回,若超時則直接返回
*/
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
接下來再看看AbstractExecutorService 同樣的套路都是實現一些公共的方法。比較關鍵的是實現了submit的那幾個方法。我們來看看。還是挺清晰明瞭的,都是將任務封裝爲一個FutureTask 然後調用execute(Runable command)方法。FutureTask 是啥??我們後面再解釋解釋。
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
接下來的分析就進入到重頭戲了。ThreadPoolExecutor。先來看看主要的成員變量
/**
* 高三位標識線程池狀態,低29位標識線程數量
*
* /
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
/**
* 阻塞隊列,存放任務
*
*/
private final BlockingQueue<Runnable> workQueue;
/**
* 鎖對象 進行關鍵操作的時候進行上鎖。
*/
private final ReentrantLock mainLock = new ReentrantLock();
/**
* 存放封裝工作線程的Worker
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
/**
* Wait condition to support awaitTermination
*/
private final Condition termination = mainLock.newCondition();
/**
* Tracks largest attained pool size. Accessed only under
* mainLock.
*/
private int largestPoolSize;
/**
* Counter for completed tasks. Updated only on termination of
* worker threads. Accessed only under mainLock.
*/
private long completedTaskCount;
/**
* 線程工廠
*/
private volatile ThreadFactory threadFactory;
/**
* 拒絕策略
* Handler called when saturated or shutdown in execute.
*/
private volatile RejectedExecutionHandler handler;
/**
* 空閒存活時間
*/
private volatile long keepAliveTime;
/**
* 核心線程數量
*/
private volatile int corePoolSize;
/**
* 最大線程數量
*/
private volatile int maximumPoolSize;
線程池的狀態有以下幾個,存保存在ctl的高三位(通過位移操作 左移表示*2,右移表示除以2)
private static final int RUNNING = -1 << COUNT_BITS;
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的構造方法基本上是由以下幾個參數組成的
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
核心線程數,最大線程數,最大空閒時間,時間單位,阻塞隊列,線程工廠,以及拒絕策略
常見的拒絕策略有
CallerRunsPolicy (直接再提交線程中執行任務)
AbortPolicy (拋異常拒絕)
DiscardPolicy (直接丟棄)
DiscardOldestPolicy (放棄最老的任務,再次提交當前任務)
核心方法
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);
else if (workerCountOf(recheck) == 0)
// 沒有工作線程就添加一下
addWorker(null, false);
}
// 這裏實際上是放不進阻塞隊列了纔去創建新的工作器,所以對阻塞隊列的設置很關鍵了
// 要不然工作線程永遠不會達到最大的線程數
else if (!addWorker(command, false))
// 未能成功創建線程,就拒絕任務
reject(command);
}
再來看看addWorker,addWorker 主要的任務就是創建新的工作線程,其中Worker是ThreadPoolExecutor的一個成員內部類。
我們先來看看這個類,這個類主要就是來執行任務的,所以呢其關鍵成員是持有一個線程對象,其次比較關鍵的是他集成了AQS,一個非常重要的類,下次再對這個類進行分析。
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
/**
* This class will never be serialized, but we provide a
* serialVersionUID to suppress a javac warning.
*/
private static final long serialVersionUID = 6138294804551838833L;
/** 真正幹活的線程 */
final Thread thread;
/** 該工作器的首個任務,初始化的時候賦予的. */
Runnable firstTask;
/** 乾的任務的數量 */
volatile long completedTasks;
/**
* Creates with given first task and thread from ThreadFactory.
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
/** Delegates main run loop to outer runWorker */
public void run() {
runWorker(this);
}
// Lock methods
//
// The value 0 represents the unlocked state.
// The value 1 represents the locked state.
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) {
}
}
}
}
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);
// 是否已經大於核心線程數或者最大線程數
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 {
// 創建工作器
w = new Worker(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());
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;
}
線程啓動了之後,就會去執行worker 的run方法。其run()實際上是調用ThreadPoolExecutor的runWork(worker)方法。
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
// 循環去獲取任務,獲取不到這裏會阻塞,這個方法也是挺關鍵的
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
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(),爲什麼說其重要呢。因爲它涉及到線程池的一個重要思想,當線程池>coreSize 時或者線程等待時間大於最大空閒時間時,會對線程進行回收操作。
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;
}
}
}
線程池狀態演變圖
繼續來看看幾個重要的接口及相關實現
Future:用來獲取異步結果主要的方法應該是get()
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
Callable 能夠獲取結果的任務
public interface Callable<V> {
V call() throws Exception;
}
在之前我們說過無論提交的Runnbale還是Callable 最終轉化爲的都是FutureTask 。這個FutureTask是個什麼呢?我們來看看類圖
FutureTask 既實現了Runnable 接口也實現了Future接口。有一點需要注意的是在FutureTask中。Runnable 對象也是統一轉化爲Callable對象的。這是怎麼轉換的呢??看看代碼就知道了。簡單滴適配一下而已。下篇文章將對FutureTask進行深入解讀
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}