在Executors框架體系中,FutureTask用來表示可獲取結果的異步任務。FutureTask實現了Future接口,FutureTask提供了啓動和取消異步任務,查詢異步任務是否計算結束以及獲取最終的異步任務的結果的一些經常使用的方法。經過get()
方法來獲取異步任務的結果,可是會阻塞當前線程直至異步任務執行結束。一旦任務執行結束,任務不能從新啓動或取消,除非調用runAndReset()
方法。在FutureTask的源碼中爲其定義了這些狀態:java
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種狀態:編程
下圖總結了FutureTask的狀態變化的過程:併發
因爲FutureTask具備這三種狀態,所以執行FutureTask的get方法和cancel方法,當前處於不一樣的狀態對應的結果也是大不相同。這裏對get方法和cancel方法作個總結:框架
get方法異步
當FutureTask處於未啓動或已啓動狀態時,執行FutureTask.get()方法將致使調用線程阻塞。若是FutureTask處於已完成狀態,調用FutureTask.get()方法將致使調用線程當即返回結果或者拋出異常spa
cancel方法線程
當FutureTask處於未啓動狀態時,執行FutureTask.cancel()方法將此任務永遠不會執行;3d
當FutureTask處於已啓動狀態時,執行FutureTask.cancel(true)方法將以中斷線程的方式來阻止任務繼續進行,若是執行FutureTask.cancel(false)將不會對正在執行任務的線程有任何影響;code
當FutureTask處於已完成狀態時,執行FutureTask.cancel(...)方法將返回false。cdn
對Future的get()方法和cancel()方法用下圖進行總結
FutureTask除了實現Future接口外,還實現了Runnable接口。所以,FutureTask能夠交給Executor執行,也能夠由調用的線程直接執行(FutureTask.run())。另外,FutureTask的獲取也能夠經過ExecutorService.submit()方法返回一個FutureTask對象,而後在經過FutureTask.get()或者FutureTask.cancel方法。
**應用場景:**當一個線程須要等待另外一個線程把某個任務執行完後它才能繼續執行,此時可使用FutureTask。假設有多個線程執行若干任務,每一個任務最多隻能被執行一次。當多個線程試圖執行同一個任務時,只容許一個線程執行任務,其餘線程須要等待這個任務執行完後才能繼續執行。
參考文獻
《java併發編程的藝術》