我正在处理一些第三方库代码,这些代码涉及创建昂贵的对象并将它们缓存在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);
}
但这似乎......有点hacky,有两个原因:
- 这项工作是在任意池化线程上完成的。我很乐意在第一个尝试获取该特定密钥的线程上完成工作,特别是因为无论如何它都会被阻止。
- 即使
Map
完全填充,我们仍然会通过Future.get()
以获得结果。我希望这很便宜,但它很难看。
我想要的是替换cache
为Map
将阻止获取给定键的获取,直到该键具有值,但同时允许其他获取。有没有这样的事情存在?或者有人有比 of 更清洁的替代品Map
吗Futures
?