當(dāng)緩存中沒(méi)有要找的數(shù)據(jù)時(shí)毁腿,則要從數(shù)據(jù)庫(kù)中去查詢日月,而當(dāng)并發(fā)量比較大時(shí)可能會(huì)擊穿數(shù)據(jù)庫(kù)纯路,所以guava cache對(duì)同一值的查詢做了合并請(qǐng)求的處理。其中就用到了SettableFuture逊拍,類似一把鎖上鞠,只會(huì)讓一個(gè)請(qǐng)求線程去查詢數(shù)據(jù)庫(kù)而其他查詢請(qǐng)求線程(查詢同一個(gè)值)會(huì)處于等待狀態(tài)。
下面是SettableFuture的UML關(guān)系圖:
從圖中我們可以看到SettableFuture實(shí)現(xiàn)了Future接口芯丧,說(shuō)明可以異步的獲取結(jié)果芍阎。它主要的實(shí)現(xiàn)繼承于AbstractFuture,而SettableFuture只是做了一層封裝注整。下面主要分析AbstractFuture能曾。
AbstractFuture包含兩個(gè)屬性:一個(gè)是內(nèi)部類Sync對(duì)象,一個(gè)是ExecutionList對(duì)象肿轨。
1.ExecutionList
ExecutionList從字面意思理解就是包含一系列execution的list,看ExecutionList的類圖可知蕊程,它有一個(gè)內(nèi)部類RunnableExecutorPair表示單向列表list中的一個(gè)節(jié)點(diǎn)椒袍,該節(jié)點(diǎn)由Runnable,Executor和next節(jié)點(diǎn)構(gòu)成藻茂,當(dāng)ExecutionList執(zhí)行execution的時(shí)候驹暑,先判斷executed是否已經(jīng)執(zhí)行過(guò)玫恳,如果沒(méi)有為了按照順序執(zhí)行任務(wù)首先會(huì)反轉(zhuǎn)單向鏈表,然后才是executor.execute(runnable)优俘。
2.Sync
Sync也是繼承AQS京办,實(shí)現(xiàn)對(duì)線程并發(fā)的控制。Sync包含5種狀態(tài)(運(yùn)行中:0帆焕,完成中:1惭婿,已完成:2,已取消:4叶雹,已中斷:8)财饥,存儲(chǔ)的值和異常。AbstractFuture類似一把共享鎖折晦,某一個(gè)時(shí)刻只能有一個(gè)線程能夠擁有AQS的state進(jìn)行寫(xiě)操作钥星,而讀的時(shí)候則可以讓多個(gè)線程同時(shí)讀。Sync中的set, setException和cancel操作都是寫(xiě)操作满着。SettableFuture中調(diào)用set的過(guò)程是這樣的:當(dāng)有一個(gè)線程調(diào)用set操作或setException時(shí)谦炒,其他寫(xiě)線程只能進(jìn)入同步隊(duì)列中進(jìn)行等待,而其他讀線程會(huì)根據(jù)Sync當(dāng)前的狀態(tài)返回對(duì)應(yīng)的結(jié)果风喇。而且AQS的state初始值是0宁改,不管是set,setException和cancel操作后响驴,state的值都不會(huì)為再為0透且,而是各個(gè)操作后的狀態(tài)值。如果同時(shí)有多個(gè)線程訪問(wèn)豁鲤,只有一個(gè)線程的操作會(huì)被接受秽誊,其他線程只有等待擁有鎖的線程完成該操作,并獲取那個(gè)操作的結(jié)果琳骡。