我在使用 Guava Caches 时得到了我不太了解的结果。
我正在实现一个我想异步刷新的单键缓存。
我每秒都会访问缓存,并将 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();
}
}