現實中,不可能把所有的資料全部放到記憶體中。您必須決定:什麼時候不值得保留緩存條目?guava提供了三種基本類型的資料驅逐:基于緩存對象大小的驅逐、基于時間的驅逐和基于引用的驅逐。
基于緩存對象大小(權重)的驅逐
如果你的緩存對象數量不會增長超過一定的大小,隻需使用CacheBuilder.maximumSize(long)。緩存将嘗試逐出沒有被經常通路的資料。逐出操作會在對象數量接近限制的時候發生。
同時,你可以為不同的對象設定不同的權重,
CacheBuilder.weigher(Weigher)定義緩存對象的權重值方法,
CacheBuilder.maximumWeight(long)定義權重最大值。權重僅僅在建立的時候計算,之後都是靜态的值。
public GuavaCache() {
cache = CacheBuilder.newBuilder()
.weigher((String key,GuavaCacheData value) -> value.weight())
.maximumWeight(1000)
.build(new CacheLoader(){
@Override
public GuavaCacheData load(String key) throws ExecutionException {
//擷取資料
try {
//這裡僅僅模拟擷取資料非常慢,不要使用該代碼
Thread.sleep(2000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return new GuavaCacheData(key);
}
});
}
基于時間的驅逐
基于時間的驅逐分為2種
1)expireAfterAccess(long, TimeUnit),當緩存對象上次通路時間超過一段時間後被驅逐
2)expireAfterWrite(long, TimeUnit),當緩存對象寫入後超過一段時間後被驅逐,這個非常常用
定時過期對象在寫入期間執行定期維護,偶爾在讀取期間執行。
重新整理緩存
重新整理緩存不等于驅逐緩存。
正如LoadingCache.refresh(K)中所指定的,重新整理密鑰将為密鑰加載一個新值,可能是異步的。重新整理密鑰時仍傳回舊值(如果有),而逐出則強制檢索等待重新加載該值。
如果在重新整理時引發異常,則保留舊值,并記錄和吞入異常。
CacheLoader可以通過重寫CacheLoader.reload(K,V)指定重新整理時使用的智能行為,這允許您在計算新值時使用舊值。
// Some keys don't need refreshing, and we want refreshes to be done asynchronously.
LoadingCachegraphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.refreshAfterWrite(1, TimeUnit.MINUTES)
.build(
new CacheLoader() {
public Graph load(Key key) { // no checked exception
return getGraphFromDatabase(key);
}
public ListenableFuturereload(final Key key, Graph prevGraph) {
if (neverNeedsRefresh(key)) {
return Futures.immediateFuture(prevGraph);
} else {
// asynchronous!
ListenableFutureTasktask = ListenableFutureTask.create(new Callable() {
public Graph call() {
return getGraphFromDatabase(key);
}
});
executor.execute(task);
return task;
}
}
});
可以使用CacheBuilder.refreshAfterWrite(long,TimeUnit)将自動定時重新整理添加到緩存中。與expireAfterWrite相反,refreshAfterWrite将使密鑰在指定的持續時間後符合重新整理條件,但隻有在查詢條目時才實際啟動重新整理。(如果CacheLoader.reload被實作為異步的,那麼查詢不會因為重新整理而變慢。)例如,您可以在同一個緩存上同時指定refreshAfterWrite和expireAfterWrite,這樣當一個條目符合重新整理條件時,條目上的過期計時器就不會盲目地重置,是以如果沒有查詢條目當它符合重新整理條件後,就可以過期了。