Per-Key-Blocking-Map in Java
Ich habe es mit Bibliothekscode von Drittanbietern zu tun, bei dem teure Objekte erstellt und in a zwischengespeichert werdenMap
. Die vorhandene Implementierung ist so etwas wie
lock.lock()
try {
Foo result = cache.get(key);
if (result == null) {
result = createFooExpensively(key);
cache.put(key, result);
}
return result;
} finally {
lock.unlock();
}
Offensichtlich ist dies nicht das beste Design, wennFoos
für verschiedenekeys
kann unabhängig erstellt werden.
Mein aktueller Hack ist die Verwendung von aMap
vonFutures
:
lock.lock();
Future<Foo> future;
try {
future = allFutures.get(key);
if (future == null) {
future = executorService.submit(new Callable<Foo>() {
public Foo call() {
return createFooExpensively(key);
}
});
allFutures.put(key, future);
}
} finally {
lock.unlock();
}
try {
return future.get();
} catch (InterruptedException e) {
throw new MyRuntimeException(e);
} catch (ExecutionException e) {
throw new MyRuntimeException(e);
}
Aber das scheint ... aus zwei Gründen ein bisschen hacky zu sein:
Die Arbeit wird an einem beliebigen gepoolten Thread ausgeführt. Ich würde mich freuen, wenn ich die Arbeit an dem ersten Thread erledigen könnte, der versucht, diesen bestimmten Schlüssel zu erhalten, zumal er sowieso blockiert wird.Auch wenn dieMap
ist voll besiedelt, wir gehen noch durchFuture.get()
um die Ergebnisse zu erhalten. Ich denke, das ist ziemlich billig, aber es ist hässlich.Was ich möchte, ist zu ersetzencache
mit einerMap
das wird blockieren bekommenfür einen bestimmten Schlüssel bis dieser schlüssel einen wert hat, andere aber in der zwischenzeit bekommt. Gibt es so etwas? Oder hat jemand eine sauberere Alternative zumMap
vonFutures
?