[英]Guava caching refreshAfterWrite confusion
使用Guava緩存時,我得到的結果我不太了解。
我正在實現一個要異步刷新的單鍵緩存。
我每秒訪問一次緩存,並且將refreshAfterWrite設置為20秒。 我的加載/重新加載功能需要5秒鍾。
如果我在加載/重新加載方法的開始時打印當前時間-我會期望得到如下結果:
載入電話從00:00:00開始
重新加載電話始於00:00:25
重新加載電話始於00:00:50
因此,加載將花費5秒,而下一次寫入將在此之后20秒觸發(5 + 20 = 25)。 該寫操作將在此之后的50秒(25 + 5 + 20 = 50)秒發生。
相反,我得到:
載入電話從00:00:00開始
重新加載電話始於00:00:25
重新加載電話始於00:00:30
這表明第二次重新加載是在第一次重新加載完成處理后立即進行的。
我以為會在處理完將來之后進行寫操作,因此下一次重新加載會安排在此之后20秒嗎?
我是否已發現錯誤或對refreshAfterWrite的工作原理有基本的誤解?
示例代碼如下:
private static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
public static void main(String[] args) throws ExecutionException, InterruptedException {
final ExecutorService executor = Executors.newFixedThreadPool(3);
final LoadingCache<String, Long> cache = CacheBuilder.newBuilder().maximumSize(1) //
.refreshAfterWrite(20, TimeUnit.SECONDS)//
.build(new CacheLoader<String, Long>() {//
public Long load(String key) {
return getLongRunningProcess("load", key);
}
public ListenableFuture<Long> reload(final String key, Long prevGraph) {
ListenableFutureTask<Long> task = ListenableFutureTask.create(new Callable<Long>() {
public Long call() {
return getLongRunningProcess("reload", key);
}
});
executor.execute(task);
return task;
}
});
while (true) {
Thread.sleep(1000L);
cache.get(CACHE_KEY);
}
}
private static Long getLongRunningProcess(String callType, String key) {
System.out.printf("%s call started at %s\n", callType, format.format(new Date()));
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return counter.getAndIncrement();
}
}
我認為您已經找到了合法錯誤。 (我幫助維護common.cache
。)
如果我正確地遵循事情,我相信一系列事件如下:
假設get A是導致刷新的第一個get
,而get B是之后的第一個get
。
scheduleRefresh
,這將在執行scheduleRefresh
中啟動refresh
任務。 將條目值引用替換為LoadingValueReference
,並且loadAsync
添加一個偵聽器,等待重新加載完成。 scheduleRefresh
。 訪問時間尚未更新,因此將繼續進行,並進入insertLoadingValueReference
。 StrongValueReference
替換值引用。 鎖被釋放。 (更新:提交https://code.google.com/p/guava-libraries/issues/detail?id=1211 。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.