Ich habe es mit Code von Drittanbietern zu tun, bei dem teure Objekte erstellt und in einer Map
zwischengespeichert werden. Die bestehende Implementierung ist so etwas wiePro-Key-Blockierungskarte in Java
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 ist, wenn Foos
für verschiedene keys
können unabhängig erstellt werden.
Mein aktueller Hack ist ein verwenden Map
von Futures
:
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 ... ein wenig hacky, aus zwei Gründen:
- Die Arbeit an einer beliebigen gepoolten erfolgt Faden. Ich würde mich freuen, die Arbeit auf dem ersten Thread zu haben, der versucht, diesen bestimmten Schlüssel zu bekommen, besonders seit wird es sowieso blockiert werden.
- Auch wenn die
Map
vollständig bestückt ist, gehen wir noch durchFuture.get()
, um die Ergebnisse zu erhalten. Ich denke, das ist ziemlich billig, aber es ist hässlich.
Was würde Ich mag ist cache
mit einem Map
zu ersetzen, die für einen bestimmten Schlüssel wird blockiert, bis dieser Schlüssel einen Wert hat, aber zulassen, dass andere mittlerweile bekommt. Gibt es so etwas? Oder hat jemand eine sauberere Alternative zu Map
von Futures
?
Shop die wichtigsten Objekte in einem 'ConcurrentHashMap' und sperre auf die wichtigsten Objekte selbst? Wenn die Schlüssel intrinsics (int, 'String', usw.) sind, wickle sie um. –
Das klingt fast so, als ob Sie eine Guave ['Striped'] möchten (http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/util/concurrent/Striped.html), die als eine Karte von Objekten zu Sperren fungiert. –