天天看點

java 清理頁面緩存資料_Java:本地緩存之google guava cache 使用之資料清理

現實中,不可能把所有的資料全部放到記憶體中。您必須決定:什麼時候不值得保留緩存條目?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,這樣當一個條目符合重新整理條件時,條目上的過期計時器就不會盲目地重置,是以如果沒有查詢條目當它符合重新整理條件後,就可以過期了。