Von When Does Cleanup Happen? · CachesExplained · google/guava Wiki:
mit CacheBuilder
gebaut Caches nicht Bereinigung durchführen und Werte zu vertreiben "automatisch" oder sofort nach einem Wert abläuft, oder irgendetwas von die Sorte. Stattdessen führt es kleine Wartungsaufgaben während Schreiboperationen aus oder während gelegentlicher Lesevorgänge, wenn Schreibvorgänge selten sind.
Der Grund hierfür ist wie folgt: Wenn wir kontinuierlich Cache
Wartung durchführen wollten, würden wir einen Thread erstellen müssen, und seine Operationen mit Benutzeroperationen für gemeinsame Sperren würde konkurrieren. Darüber hinaus beschränken einige Umgebungen die Erstellung von Threads , die CacheBuilder
in dieser Umgebung unbrauchbar machen würde.
Stattdessen legen wir die Wahl in Ihre Hände. Wenn Ihr Cache High-Throughput ist, müssen Sie sich nicht darum kümmern, die Cache Wartung durchzuführen, um abgelaufene Einträge und ähnliches zu bereinigen. Wenn Ihr Cache nur selten schreibt und Sie nicht möchten, Cache zu blockieren, möchten Sie möglicherweise einen eigenen Wartungs-Thread erstellen, der in regelmäßigen Abständen Cache.cleanUp()
aufruft.
Wenn Sie regelmäßig die Cache-Pflege für einen Cache planen möchten, die nur selten schreibt hat, planen nur die Wartung mit ScheduledExecutorService
.
Als solcher, wenn Sie nur tun, liest man „könnte“ gut sein, wenn Sie ein Cache.cleanUp()
tun kurz vor und nach der Transaktion, aber es gibt immer noch keine Garantie.
Anstatt jedoch zu erzwingen, dass Objekte im Cache verbleiben, können Sie stattdessen Elemente einfach in einen anderen Cache/Map mithilfe einer removalListener
räumen. Wenn Sie dann lesen, müssen Sie zunächst den Cache überprüfen und dann Überprüfen Sie die Artikel, die während der langwierigen Transaktion gelöscht wurden.
Das Folgende ist ein stark vereinfachte Beispiel:
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");
Ihr eigentlicher Code benötigen würde bedingt put
in evicted
, clean-up evicted
, verwaltet mehrere evicted
Objekte, wenn Ihr Lauf lang laufende Transaktionen gleichzeitig oder Verwendung ein gemeinsamer Cache zwischen den Threads mit einer anderen Eviction-Strategie, etc., aber hoffentlich zeigt dies die Idee ausreichend, um Ihnen den Einstieg zu erleichtern.
Ich hoffte auf etwas, das eingebaut ist, mit dem Sie die automatische Räumung verhindern können, während eine Transaktion läuft. – Yash
Richtig, ich habe es nicht explizit gesagt, aber von dem, was ich sagen kann, gibt es keine solche Funktion eingebaut. – mfulton26