1. 程式人生 > >guava中的SettableFuture分析

guava中的SettableFuture分析

沒有 ext 分析 runnable 查詢 rac 兩個 理解 同步隊列

當緩存中沒有要找的數據時,則要從數據庫中去查詢,而當並發量比較大時可能會擊穿數據庫,所以guava cache對同一值的查詢做了合並請求的處理。其中就用到了SettableFuture,類似一把鎖,只會讓一個請求線程去查詢數據庫而其他查詢請求線程(查詢同一個值)會處於等待狀態。
下面是SettableFuture的UML關系圖:

技術分享圖片

從圖中我們可以看到SettableFuture實現了Future接口,說明可以異步的獲取結果。它主要的實現繼承於AbstractFuture,而SettableFuture只是做了一層封裝。下面主要分析AbstractFuture。
AbstractFuture包含兩個屬性:一個是內部類Sync對象,一個是ExecutionList對象。
1.ExecutionList
技術分享圖片

ExecutionList從字面意思理解就是包含一系列execution的list,看ExecutionList的類圖可知,它有一個內部類RunnableExecutorPair表示單向列表list中的一個節點,該節點由Runnable,Executor和next節點構成,當ExecutionList執行execution的時候,先判斷executed是否已經執行過,如果沒有為了按照順序執行任務首先會反轉單向鏈表,然後才是executor.execute(runnable)。

2.Sync
技術分享圖片

Sync也是繼承AQS,實現對線程並發的控制。Sync包含5種狀態(運行中:0,完成中:1,已完成:2,已取消:4,已中斷:8),存儲的值和異常。AbstractFuture類似一把共享鎖,某一個時刻只能有一個線程能夠擁有AQS的state進行寫操作,而讀的時候則可以讓多個線程同時讀。Sync中的set, setException和cancel操作都是寫操作。SettableFuture中調用set的過程是這樣的:當有一個線程調用set操作或setException時,其他寫線程只能進入同步隊列中進行等待,而其他讀線程會根據Sync當前的狀態返回對應的結果。而且AQS的state初始值是0,不管是set,setException和cancel操作後,state的值都不會為再為0,而是各個操作後的狀態值。如果同時有多個線程訪問,只有一個線程的操作會被接受,其他線程只有等待擁有鎖的線程完成該操作,並獲取那個操作的結果。

guava中的SettableFuture分析