Карта блокировки по ключам в Java

Я имею дело с некоторым сторонним библиотечным кодом, который включает создание дорогих объектов и кэширование их вMap, Существующая реализация что-то вроде

lock.lock()
try {
    Foo result = cache.get(key);
    if (result == null) {
        result = createFooExpensively(key);
        cache.put(key, result);
    }
    return result;
} finally {
    lock.unlock();
}

Очевидно, что это не лучший дизайн, когдаFoos для разныхkeys может быть создан независимо.

Мой текущий взлом состоит в том, чтобы использоватьMap из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);
}

Но это кажется ... немного странным по двум причинам:

Работа выполняется в произвольной объединенной ветке. Я был бы рад сделать работу над первым потоком, который пытается получить этот конкретный ключ, тем более что он все равно будет заблокирован.Даже когдаMap полностью заселена, мы все еще переживаемFuture.get() чтобы получить результаты. Я ожидаю, что это довольно дешево, но это ужасно.

Что я хотел бы заменитьcache сMap что заблокирует получаетдля данного ключа пока этот ключ не имеет значения, но разрешить другим становится тем временем. Существует ли такая вещь? Или у кого-то есть более чистая альтернативаMap изFutures?

Ответы на вопрос(3)

Ваш ответ на вопрос