Guava キャッシュを使用しているときに、よくわからない結果が得られます。
非同期で更新したい単一のキーキャッシュを実装しています。
毎秒キャッシュにアクセスし、refreshAfterWrite を 20 秒に設定しました。私のロード/リロード機能には 5 秒かかります。
load/reload メソッドの開始時に現在の時刻を出力すると、次のような結果が期待されます。
load 呼び出しは 00:00:00 に開始されました reload 呼び出し
は 00:00:25 に開始されました
reload 呼び出しは 00:00:50 に開始されました
したがって、ロードには 5 秒かかり、次の書き込みはその後 20 秒 (5+20=25) トリガーされます。その書き込みは、その後 50 秒 (25 + 5 + 20 = 50) 秒後に発生します。
代わりに私は得る:
load 呼び出しは 00:00:00 に開始されました reload 呼び出し
は 00:00:25 に開始されました
reload 呼び出しは 00:00:30 に開始されました
これは、最初のリロードの処理が完了した直後に 2 回目のリロードが発生したことを示しています。
未来が処理された後に書き込みが発生すると思ったので、次のリロードはその後 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();
}
}