FutureTask基本操作總結

你聽___發表於2018-05-06

FutureTask基本操作總結

1.FutureTask簡介

在Executors框架體系中,FutureTask用來表示可獲取結果的非同步任務。FutureTask實現了Future介面,FutureTask提供了啟動和取消非同步任務,查詢非同步任務是否計算結束以及獲取最終的非同步任務的結果的一些常用的方法。通過get()方法來獲取非同步任務的結果,但是會阻塞當前執行緒直至非同步任務執行結束。一旦任務執行結束,任務不能重新啟動或取消,除非呼叫runAndReset()方法。在FutureTask的原始碼中為其定義了這些狀態:

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;
複製程式碼

另外,在《java併發程式設計的藝術》一書,作者根據FutureTask.run()方法的執行的時機,FutureTask分為了3種狀態:

  1. 未啟動。FutureTask.run()方法還沒有被執行之前,FutureTask處於未啟動狀態。當建立一個FutureTask,還沒有執行FutureTask.run()方法之前,FutureTask處於未啟動狀態。
  2. 已啟動。FutureTask.run()方法被執行的過程中,FutureTask處於已啟動狀態。
  3. 已完成。FutureTask.run()方法執行結束,或者呼叫FutureTask.cancel(...)方法取消任務,或者在執行任務期間丟擲異常,這些情況都稱之為FutureTask的已完成狀態。

下圖總結了FutureTask的狀態變化的過程:

FutureTask狀態遷移圖.jpg

由於FutureTask具有這三種狀態,因此執行FutureTask的get方法和cancel方法,當前處於不同的狀態對應的結果也是大不相同。這裡對get方法和cancel方法做個總結:

get方法

當FutureTask處於未啟動或已啟動狀態時,執行FutureTask.get()方法將導致呼叫執行緒阻塞。如果FutureTask處於已完成狀態,呼叫FutureTask.get()方法將導致呼叫執行緒立即返回結果或者丟擲異常

cancel方法

當FutureTask處於未啟動狀態時,執行FutureTask.cancel()方法將此任務永遠不會執行;

當FutureTask處於已啟動狀態時,執行FutureTask.cancel(true)方法將以中斷執行緒的方式來阻止任務繼續進行,如果執行FutureTask.cancel(false)將不會對正在執行任務的執行緒有任何影響;

FutureTask處於已完成狀態時,執行FutureTask.cancel(...)方法將返回false。

對Future的get()方法和cancel()方法用下圖進行總結

FutureTask的get和cancel的執行示意圖.jpg

2. FutureTask的基本使用

FutureTask除了實現Future介面外,還實現了Runnable介面。因此,FutureTask可以交給Executor執行,也可以由呼叫的執行緒直接執行(FutureTask.run())。另外,FutureTask的獲取也可以通過ExecutorService.submit()方法返回一個FutureTask物件,然後在通過FutureTask.get()或者FutureTask.cancel方法。

**應用場景:**當一個執行緒需要等待另一個執行緒把某個任務執行完後它才能繼續執行,此時可以使用FutureTask。假設有多個執行緒執行若干任務,每個任務最多隻能被執行一次。當多個執行緒試圖執行同一個任務時,只允許一個執行緒執行任務,其他執行緒需要等待這個任務執行完後才能繼續執行。

參考文獻

《java併發程式設計的藝術》

相關文章