Guava Cache使用的三種姿勢
- 2021 年 7 月 22 日
- 筆記
- cache, Guava Cache, JAVA, Java隨筆
姿勢一
使用expiredAferWriter
優點
- 簡單
- 粗暴
缺點
- 同步阻塞問題:如果多個執行緒同時請求同一個過期的key,只有一個執行緒能夠獲得去載入快取的鎖,但是其他未獲取載入快取鎖的執行緒也會阻塞。
show me the code
姿勢二
使用expiredAfterWrite + refreshAfterWrite
使用注意
指定refreshAferWrite的時間小於expiredAfterWrite
必須使用LoadingCache
直接使用get獲取快取
優點
- 當到達刷新時間之後,只會有一個執行緒獲得刷新快取的鎖,其他執行緒直接返回快取中的舊值,僅阻塞刷新快取的執行緒
缺點
- 刷新快取的執行緒還是會被阻塞
show me the code
姿勢三
使用expiredAfterWrite + refreshAfterWrite + ListenableFuture
優點
- 刷新快取的執行緒也不會被阻塞,而是直接返回
缺點
- 刷新快取的執行緒得到的仍然是舊值
- 快取的刷新或者重新載入還是得靠外部請求觸發,不能完全達到定時刷新效果
注意
1. 不管上面那種方式,快取的載入和刷新都需要外部調用(get)才觸發
2. 使用姿勢二和三要注意快取的刷新過期時間要設置的比載入過期時間短,否則體現不出優勢
3. 如果當前請求快取時間距離最後一次時間已經超過過期時間,則會調用載入(load)方法而非刷新(reload)方法來載入快取,此時會回退到姿勢一
4. 刷新快取的同時也會刷新快取下次過期的時間(在當前時間累加過期時間)
5. 具體邏輯參照**com.google.common.cache.LocalCache$Segment**。這裡貼出一些關鍵邏輯供各位參考:
只有在value!=null的時候(既未達到過期時間時)才會調用refresh方法
註冊了一個Listener來實現非同步刷新