When Does Cleanup Happen? · CachesExplained · google/guava Wikiから:CacheBuilder
で構築された
キャッシュはないクリーンアップを実行し、値の有効期限が切れた後 "自動" または瞬時値を立ち退かせる、または何もありません ソート。代わりに、 書き込み操作の間に、または書き込みがほんの少しの場合は、読み取り操作中に少量のメンテナンスを実行します( )。我々は継続的にCache
メンテナンスを実行したい場合、我々はスレッドを作成する必要があり、そしてその 操作は共有ロックのためのユーザ操作と競合することになります。
その理由は次のとおりです。 さらに、一部の環境では、スレッドの作成が制限されます。 は、その環境でCacheBuilder
を使用できなくします。
代わりに、私たちは選択肢をあなたの手に入れます。キャッシュが ハイスループットの場合、キャッシュ のメンテナンスを実行して期限切れのエントリをクリーンアップするなどの心配はありません。キャッシュ がめったに書き込みを行わず、クリーンアップでキャッシュ の読み取りをブロックしたくない場合は、定期的に Cache.cleanUp()
を呼び出す独自のメンテナンススレッドを作成したい場合があります。
に書き込みがほとんどないキャッシュの定期的なキャッシュメンテナンスをスケジュールする場合は、 ScheduledExecutorService
を使用してメンテナンスをスケジュールしてください。
このように、取引の前後にCache.cleanUp()
を行うと、あなたが読んでいるだけでよいかもしれませんが、保証はありません。
しかし、アイテムをキャッシュに残そうとするのではなく、removalListener
を使用してアイテムを別のキャッシュ/マップに退避させてから、最初にキャッシュを確認してから、長期実行トランザクション中に削除された項目をチェックします。
次は単純化しすぎの例である:あなたの実際のコードは、あなたが同時に長時間実行されるトランザクションを実行しているか、使用している場合は、複数のevicted
オブジェクトを管理、クリーンアップevicted
に条件付きでput
evicted
に必要があるだろう
Map<Integer, String> evicted = new ConcurrentHashMap<>();
Cache<Integer, String> cache = CacheBuilder.newBuilder()
.expireAfterAccess(2, SECONDS)
.removalListener((RemovalListener<Integer, String>) notification ->
evicted.put(notification.getKey(), notification.getValue()))
.build();
assert evicted.size() == 0 && cache.size() == 0;
cache.put(0, "a");
cache.put(1, "b");
cache.put(2, "c");
assert evicted.size() == 0 && cache.size() == 3;
sleepUninterruptibly(1, SECONDS);
assert evicted.size() == 0 && cache.size() == 3;
cache.put(3, "d");
assert evicted.size() == 0 && cache.size() == 4;
sleepUninterruptibly(1, SECONDS);
cache.cleanUp();
assert evicted.size() == 3 && cache.size() == 1;
Integer key = 2;
String value;
{
value = cache.getIfPresent(key);
if (value == null) value = evicted.get(key);
}
assert Objects.equals(value, "c");
別の追い出し戦略を持つスレッド間の共通のキャッシュなどがありますが、うまくいけば、これはあなたを始めるための十分なアイデアを示しています。
私はトランザクションが進行中に自動追い出しを防ぐことができる内蔵のものを期待していました。 – Yash
そうですね、私はそれを明示していませんでしたが、私が知る限り、このような機能は組み込まれていません。 – mfulton26