JUC FutureTask我的理解

clipboard.png

FutureTask是一個可取消的異步計算框架。其中內部用的是state來記錄任務的執行狀態。
clipboard.pngjava

如上所示FutrueTask內部封裝了以上的Object。全部經過調用Futuretask執行的任務都會在齊內部包裝成一個callable來執行。node

clipboard.png
clipboard.png

以上貼出的兩個FutureTask的構造函數,要麼直接構造一個實現了callable接口的對象,要麼傳入一個實現Runnable接口的對象,在其內部將Runnable轉換爲callable。多線程

FutureTask的執行:

接下來看看FutureTask的核心方法
clipboard.png框架

可經過將FutureTask放入一個線程,或者將其放入線程池中實現調用。其中set()和setException()會喚醒存在waiters中的node,告訴他們計算已經完成,或者計算中拋出了異常。
在set()、setException()和cancel()方法的末尾都會調用finishCompletion()方法來釋放存在waiters中的線程,在該方法中還有一個done()方法,用來讓子類實現,作一些異步任務完成以後的事情。
看看cancel()方法
clipboard.png異步

須要注意的是任務只有在state == NEW的時候才能被取消。函數


FutureTask結果的獲取:

FutureTask可經過get()調用獲得計算的結果,若是計算還沒完成,該方法會阻塞,也可響應中斷。產生阻塞的時候會將線程wrap成node加入到waiters中。下面看看get中調用的awaitDone(boolean timed, long nanos)方法
clipboard.pngthis

awaitDone代碼中採起死循環的方式:
檢查是否響應中斷,如果,則移除該node,拋出中斷異常。spa

if (Thread.interrupted()) {
    removeWaiter(q);
    throw new InterruptedException();
}

若此時已經結束,返回此時的狀態值。線程

int s = state;
if (s > COMPLETING) {
    if (q != null)
    q.thread = null;
    return s;
}

若判斷爲如下狀況則暫時讓出cpu時間,稍後執行,由於COMPLETING是一個瞬時的狀態,說明這個時候計算結果已經立刻要被set了,或者也多是拋出了異常。code

else if (s == COMPLETING) // cannot time out yet
          Thread.yield();

若判斷爲如下狀況則新建一個node,該node包裝了當前的線程。

else if (q == null)
         q = new WaitNode()

若判斷爲如下狀況則將node加入到waiters中

else if (!queued)
    queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);

接下來最後的兩個判斷都是park這個線程,只是有時間的區分。

總結

利用FutureTask和ExecutorService,能夠用多線程的方式提交計算任務,主線程繼續執行其餘任務,當主線程須要子線程的計算結果時,在異步獲取子線程的執行結果。

相關文章
相關標籤/搜索