【发布时间】:2013-05-29 18:56:30
【问题描述】:
我正在处理一些第三方库代码,这些代码涉及创建昂贵的对象并将它们缓存在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()来获取 结果。我认为这很便宜,但它很丑。
我想要的是用Map 替换cache,这将阻止获取给定键的,直到该键具有值,但同时允许其他获取。有没有这样的东西存在?或者有人有比Map 或Futures 更干净的替代品吗?
【问题讨论】:
-
将关键对象存储在
ConcurrentHashMap中并锁定关键对象本身?如果键是内在函数(int、String等),则包装它们。 -
这听起来就像你想要一个 Guava
Striped,它充当从对象到锁的映射。
标签: java concurrency java.util.concurrent