天天看點

Future和FutureTask

1,Future

       java.util.concurrent.Future接口提供了線程不會因為等待傳回結果而阻塞的能力。

       設想一個生活場景,用于需要申請車牌,它在送出了申請之後,與長達數小時的等待過程,在這個過程裡,使用者可以做自己想做的其他事情,而無需一直在視窗等待車牌制作完成。

       在這個過程中,用于可以放棄領取,也可以一直在視窗等待,也可以在視窗看看,能拿走則拿走,不行就在等一會去做别的事。

       Future模式就是提供了這樣的能力,讓線程可以靈活的确定自己在何時取得結果。

2,FutureTask

       java.util.concurrent.FutureTask是Future接口在concurrency包中的預設實作,它的主要用途之一是為了AbstractExecutorService提供任務支援,交由AbstractExecutorService執行的任務會被包裝成一個FutureTask,以提供延時擷取傳回值的能力。

       FutureTask間接繼承自Future接口和Runnable接口,是以,它同時具備執行任務和擷取結果兩種能力,FutureTask把實作委托給了其内部的AQS來實作。

       AQS是一個抽象隊列同步器,内部維護了一個等待隊列和等待狀态。

3,Sync的四種狀态

       Sync設計了四種狀态,可見,Sync的實作也采用了狀态機模式。

READY:任務準備完畢,可以運作

RUNNING:任務正在運作

RAN:任務運作完畢

CANCELLED:任務取消

4,Sync的運作

       innerRun的實作很簡單:

1)       檢查任務是否為READY狀态,如果不是,那麼認為已經被調用過了,直接傳回。

2)       設定任務為RUNNING狀态,表示目前Sync申領了該任務,如果該任務沒有被其它線程修改,那麼執行該任務。

3)       如果其它線程修改了該任務額狀态,例如RAN或者CANCELLED,那麼中斷執行。

5,Sync的取消

       innerCancel方法的關鍵點有幾處:

1)       隻有READY或者RUN狀态的任務才能取消。

2)       根據參數來決定是否要中斷線程阻塞。

6,Sync擷取資料

       innerGet方法用于異步擷取資料,其邏輯實作如下:

1)       如果任務已經執行完成了,那麼直接傳回結果。

2)       如果任務尚未完成,那麼等待任務完成後傳回結果。

       通過對innerGet邏輯實作的分析,可以得出:

1)       線程通路innerGet時,如果任務不是RAN或者CANCELLED狀态,那麼線程會被阻塞。

2)       result來自于innerRun()裡callable的傳回值

7,Sync和AQS

     在運作/取消方法裡,調用了tryReleaseShared,在取值方法裡,調用了tryAcquiredShared,這兩個try方法來自于AQS,分别用于在共享模式下線程釋放鎖和持有鎖