簡介
FutureTask,可取消的異步計算。利用開始和取消計算的方法、查詢計算是否完成的方法和獲取計算結果的方法,此類提供了對 Future 的基本實現。僅在計算完成時才能獲取結果;如果計算尚未完成,則阻塞 get 方法。一旦計算完成,就不能再重新開始或取消計算。可使用 FutureTask 包裝 Callable 或 Runnable 對象。因爲 FutureTask 實現了 Runnable,所以可將 FutureTask 提交給 Executor 執行。
源碼分析
FutureTask類繼承關係
FutureTask類實現了RunnableFuture接口,RunnableFuture接口繼承自Future接口和Runnable接口,整合了一下Future接口和Runnable接口。
其中的方法在FutureTask中做了具體的實現。
- Future接口表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。計算完成後只能使用 get 方法來獲取結果,如有必要,計算完成前可以阻塞此方法。取消則由 cancel 方法來執行。還提供了其他方法,以確定任務是正常完成還是被取消了。一旦計算完成,就不能再取消計算。
- Runnable接口是爲了方便把FutureTask提交給線程池,線程池中的工作線程將調用他的 run 方法。
public interface Future<V> {
//試圖取消對此任務的執行
boolean cancel(boolean mayInterruptIfRunning);
//如果在任務正常完成前將其取消,則返回 true。
boolean isCancelled();
//如果任務已完成,則返回 true。
boolean isDone();
//如有必要,等待計算完成,然後獲取其結果。
V get() throws InterruptedException, ExecutionException;
//如有必要,最多等待爲使計算完成所給定的時間之後,獲取其結果(如果結果可用)。
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
public interface Runnable {
public abstract void run();
}
FutureTask核心屬性
/**
* 狀態扭轉
* NEW -> COMPLETING -> NORMAL //正常完成
* NEW -> COMPLETING -> EXCEPTIONAL //異常
* NEW -> CANCELLED //取消
* NEW -> INTERRUPTING -> INTERRUPTED //中斷
*/
private volatile int state;//Future狀態
private static final int NEW = 0;//初始化
private static final int COMPLETING = 1;//運行中
private static final int NORMAL = 2;//正常完成
private static final int EXCEPTIONAL = 3;//異常
private static final int CANCELLED = 4;//已取消
private static final int INTERRUPTING = 5;//中斷中
private static final int INTERRUPTED = 6;//中斷完成
//內部的callable,運行完成後設置爲null
private Callable<V> callable;
//從get方法返回或者拋出異常
private Object outcome; //沒有volatile修飾, 通過狀態字段state讀寫保證了可見性
//執行內部callable的線程
private volatile Thread runner;
/**
* Treiber stack 等待線程的非阻塞堆棧,存放所有等待的線程
* 首先獲取當前最頂的節點,創建一個新節點放在堆棧上,
* 如果最頂端的節點在獲取之後沒有變化,那麼就設置上新節點。
* 如果 CAS 失敗,意味着另一個線程已經修改了堆棧,
* 那麼會重新執行上述操作。
*/
private volatile WaitNode waiters;
static final class WaitNode {//包含了當前線程對象,並有指向下一個WaitNode的指針next,Treiber Stack就是由WaitNode組成的一個單向鏈表。
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
}
FutureTask核心方法源碼分析
構造方法
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;//volatile寫保證callable的可見性
}
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);//包裝成一個Callable
this.state = NEW;//volatile寫保證callable的
}
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
static final class RunnableAdapter<T> implements Callable<T> {//把Runnable包裝成一個Callable,在線程池中會執行FutureTask的run方法,在FutureTask的run方法中會執行Callable的call方法,在這個RunnableAdapter中會執行task的run方法。
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
核心運行方法run()
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread()))//如果當前狀態不是NEW,或者狀態是NEW但是將執行線程runner用CAS從null更新爲當前線程失敗,則直接退出
return;
try {
Callable<V> c = callable;//獲取當前需要執行的callable
if (c != null && state == NEW) {//callable不爲null且狀態是NEW,則執行業務邏輯
V result;//call方法的返回值
boolean ran;//是否正常執行完成
try {
result = c.call();//調用call方法
ran = true;//是正常完成設置true
} catch (Throwable ex) {//如果拋出異常
result = null;//設置結果爲null
ran = false;//設置非正常完成false
setException(ex);//設置異常
}
if (ran)//正常完成
set(result);//設置返回結果
}
} finally {
runner = null;//將執行線程設置爲null
int s = state;//重新讀取狀態
if (s >= INTERRUPTING)//如果是中斷的,處理中斷
handlePossibleCancellationInterrupt(s);
}
}
protected void set(V v) {//設置結果
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {//首先將狀態從NEW更改爲COMPLETING
outcome = v;//將結果負值給outcome
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); //設置結果爲NORMAL,正常完成
finishCompletion();//喚醒Treiber stack所有等待線程
}
}
protected void setException(Throwable t) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {////首先將狀態從NEW更改爲COMPLETING
outcome = t;//設置結果爲異常t
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); //設置結果爲EXCEPTIONAL,運行異常
finishCompletion();//喚醒Treiber stack所有等待線程
}
}
private void finishCompletion() {//喚醒所有等待線程
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {//如果有等待線程,設置爲q
if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {//將waiters用CAS從q設置爲null,置空所有等待線程
for (;;) {//從q開始遍歷WaitNode棧,喚醒所有的等待線程
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
}
break;
}
}
done();//執行擴展點done方法
callable = null; //將需要執行的callable設置爲null
}
private void handlePossibleCancellationInterrupt(int s) {
if (s == INTERRUPTING)//如果狀態是INTERRUPTING,則讓出cpu等待狀態變成INTERRUPTED才結束
while (state == INTERRUPTING)
Thread.yield();
}
V get() throws InterruptedException, ExecutionException
等待計算完成,然後獲取其結果。
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)//如果是初始化或者運行中狀態,則調用awaitDone等待執行完成後喚醒返回。
s = awaitDone(false, 0L);//返回結果是當前Future狀態
return report(s);//返回結果
}
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {//timed標示是否超時等待,nano代表超時等待時間
final long deadline = timed ? System.nanoTime() + nanos : 0L;//獲取最長的等待時間,支持超時是當前時間加上等待時間得到未來需要等到的最長時間點,不支持超時是0。
WaitNode q = null;//當前線程節點
boolean queued = false;//當前q節點是否加入等待線程棧中
for (;;) {
if (Thread.interrupted()) {//如果當前線程被中斷,移除當前等待節點q,然後拋出中斷異常
removeWaiter(q);//從等待線程中移除當前節點q
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {//如果已經完成則置空當前節點,並返回完成狀態
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING) //如果是COMPLETING,則意味着業務邏輯已經執行結束,讓出cpu等待最終狀態更新完成後返回
Thread.yield();
else if (q == null)//q==null時,初始化當前線程節點q
q = new WaitNode();
else if (!queued)//如果當前節點q不再等待線程棧中,則CAS將當前節點加入等待線程棧中,放在等待線程棧的頂部
queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);
else if (timed) {//如果支持超時等待,則掛起線程直到超時
nanos = deadline - System.nanoTime();
if (nanos <= 0L) {//如果已經超時,則從等待線程棧中移除當前節點q,並返回當前狀態。
removeWaiter(q);
return state;
}
LockSupport.parkNanos(this, nanos);
}
else//如果不支持超時等待,則直接掛起線程
LockSupport.park(this);
}
}
private void removeWaiter(WaitNode node) {//移除當前等待節點node
if (node != null) {
node.thread = null;//下面會將node從等待隊列中移除,以thread字段爲null爲依據,出現競爭則重試
retry:
for (;;) { // restart on removeWaiter race
for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
s = q.next;
if (q.thread != null)
pred = q;
else if (pred != null) {
pred.next = s;
if (pred.thread == null) // check for race
continue retry;
}
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
q, s))
continue retry;
}
break;
}
}
}
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)//狀態是正常完成,則直接返回outcome
return (V)x;
if (s >= CANCELLED)//如果是取消後的狀態,則直接返回CancellationException,中斷也是屬於取消的狀態
throw new CancellationException();
throw new ExecutionException((Throwable)x);//其他狀態都返回ExecutionException
}
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
最多等待爲使計算完成所給定的時間之後,獲取其結果(如果結果可用)。
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null)
throw new NullPointerException();
int s = state;
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)//超時等待,如果從awaitDone返回時,狀態還是NEW或者COMPLETING,則意味着超時,拋出超時異常
throw new TimeoutException();
return report(s);
}
boolean cancel(boolean mayInterruptIfRunning)
試圖取消對此任務的執行。如果任務已完成、或已取消,或者由於某些其他原因而無法取消,則此嘗試將失敗。當調用 cancel 時,如果調用成功,而此任務尚未啓動,則此任務將永不運行。如果任務已經啓動,則 mayInterruptIfRunning 參數確定是否應該以試圖停止任務的方式來中斷執行此任務的線程。如果此時業務方法在執行中且FutureTask狀態還是NEW時,可以取消FutureTask,但是無法停止業務方法的執行,取消之後,即使業務方法執行完畢也無法獲取執行結果,因爲FutureTask狀態是取消的。
public boolean cancel(boolean mayInterruptIfRunning) {
if (state != NEW)//如果是NEW狀態,則一定沒取消返回false
return false;
if (mayInterruptIfRunning) {//如果強制取消則中斷的方式取消任務
if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))//用CAS將state從NEW更新到INTERRUPTING,失敗則返回false取消失敗,成功則中斷運行任務的線程,然後將狀態設置爲INTERRUPTED,然後喚醒所有等待線程返回true取消成功
return false;
Thread t = runner;
if (t != null)
t.interrupt();//中斷運行線程(如果在線程池中執行任務,該中斷會中斷線程池中的工作線程,線程池中工作線程的run方法中會清除線程的中斷狀態)
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
}
else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))//如果不是強制取消,用CAS將state從NEW更新到CANCELLED,失敗則返回false取消失敗,成功則喚醒所有等待線程返回true取消成功
return false;
finishCompletion();//喚醒所有等待線程
return true;
}
boolean isCancelled()
如果在任務正常完成前將其取消,則返回 true。
public boolean isCancelled() {//大於等於CANCELLED都是取消,中斷也是取消
return state >= CANCELLED;
}
boolean isDone()
如果任務已完成,則返回 true。 可能由於正常終止、異常或取消而完成,在所有這些情況中,此方法都將返回 true。
public boolean isDone() {//不是NEW就代表已經執行完成任務,等待返回了
return state != NEW;
}
FutureTask擴展點
任務執行完成後執行,可自定義處理邏輯,做監控或記錄等等。
protected void done() { }