天天看點

和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future

1 簡介

  • 使用繼承方式的好處是友善傳參,可在子類裡面添加成員變量,通過 set 方法設定參數者通過構造器進行傳遞
  • 使用 Runnable 方式,則隻能使用主線程裡面被聲明為 final 變量

不好的地方是 Java 不支援多繼承,若繼承了 Thread 類,則子類不能再繼承其它類 ,而 Runable接口則無該限制 。

Thread 類和 Runnable 接口都不允許聲明檢查型異常,也不能定義傳回值。

沒有傳回值就有點麻煩,這兩種方式都沒辦法拿到任務的傳回結果,但FutureTask 可以!

不能聲明抛出檢查型異常則更麻煩一些。run()方法意味着必須捕獲并處理檢查型異常。即使小心地儲存了異常資訊(在捕獲異常時)以便稍後檢查,但也不能保證這個 Runnable 對象的所有使用者都讀取異常資訊。

可以修改Runnable實作的getter,讓它們都能抛出任務執行中的異常。但這種方法除了繁瑣也不是十分安全可靠,你不能強迫使用者調用這些方法,程式員很可能會調用join()方法等待線程結束然後就不管了。

但是現在不用擔心了,以上的問題終于在1.5中解決了。

Callable接口和Future接口的引入以及他們對線程池的支援優雅地解決了這兩個問題。

2 案例

FutureTask 相關元件如何使用的=

和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future

3 Callable

Callable函數式接口定義了唯一方法 - call()。可以在Callable的實作中聲明強類型的傳回值,甚至抛異常。

利用call()直接傳回結果,省去讀取值時的類型轉換。

  • 定義
  • 和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future
  • 傳回值是個泛型,使用時,不會直接使用 Callable,而是和 FutureTask 協同。

4 Future

  • Callable 可以傳回線程的執行結果,在擷取結果時,就需用到Future接口
  • 和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future
  • Future是 Java5 中引入的接口,當送出一個Callable對象給線程池時,将得到一個Future對象,并且它和傳入的Callable有相同的結果類型聲明。

它取代了Java5 前直接操作 Thread 執行個體做法。以前,不得不用Thread.join()或Thread.join(long millis)等待任務完成。

Future表示異步計算的結果,提供了一些方法來檢查計算是否完成,等待其完成以及檢索計算結果。

隻有在計算完成時才可以使用get方法檢索結果,必要時将其阻塞,直到準備就緒。

取消是通過cancel方法執行的。

提供了其他方法來确定任務是正常完成還是被取消。一旦計算完成,就不能取消計算。

如果出于可取消性的目的使用Future而不提供可用的結果,則可以聲明Future <?>形式的類型,并作為基礎任務的結果傳回null。

4.1 Future API

4.1.1 cancel - 嘗試取消執行任務

和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future

當任務處于不同狀态時,該方法有不同響應:

任務已完成 / 已取消 / 由于某些其他原因無法被取消

該嘗試會直接失敗

嘗試成功,且此時任務尚未開始

可以取消成功

任務已開始

mayInterruptIfRunning 參數确定是否可以中斷執行該任務的線程以嘗試停止該任務。

此方法傳回後,對 isDone 的後續調用将始終傳回 true。若此方法傳回 true,則随後對 isCancelled 的調用将始終傳回 true。

4.1.2 isCancelled - 是否被取消

和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future

如果此任務在正常完成之前被取消,則傳回true.

4.1.3 isDone - 是否完成

和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future

如果此任務完成,則傳回true。

完成可能是由于正常終止,異常或取消引起的,在所有這些情況下,此方法都将傳回true。

4.1.4 get - 擷取結果

等待任務完成,然後擷取其結果。

和阿裡面試官對線FutureTask源碼面試(上)1 簡介2 案例3 Callable4 Future

若:

  • 任務被取消,抛 CancellationException
  • 目前線程在等待時被中斷,抛 InterruptedException
  • 任務抛出了異常,抛 ExecutionException