我正在處理一些第三方庫代碼,這些代碼涉及創建昂貴的對象並將其緩存在Map
中。現有的實現是一樣的東西按鍵封鎖Java中的地圖
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()
獲得 的結果。我預計這很便宜,但它很醜。
我想是一個Map
,這將阻止得到對於給定的關鍵直到鍵都有一個值來代替cache
,但允許其他同時獲得。有這樣的事嗎?還是有人有一個更清潔的替代Map
Futures
?
Store中的關鍵對象的'ConcurrentHashMap'和重點對象本身鎖?如果鍵是內在的(int,'String'等),則將它們包裝起來。 –
這幾乎聽起來像你想要一個番石榴['條紋'](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/util/concurrent/Striped.html ),這種行爲是從對象到鎖的映射。 –