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?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage