考虑以下代码:
ConcurrentHashMap<String, Value> map = new ConcurrentHashMap<>();
boolean foo(String key) {
Value value = map.get(key);
if (value == null) {
value = map.putIfAbsent(key, new Value());
if (value == null) {
// do some stuff
return true;
}
}
// do some other stuff
return false;
}
Run Code Online (Sandbox Code Playgroud)
假设foo()由多个线程并发调用。还假设呼叫new Value()是昂贵的。代码很冗长,仍然会导致Value创建冗余对象。上述逻辑能否以一种保证不Value创建冗余对象的方式实现(即new Value()最多调用一次)?我正在寻找一个干净的实现 - 最少的代码而不显式获取锁。
computeIfAbsent 可能是一个不错的选择,但是它的返回语义不符合所需的逻辑。
首先,让我们解决您没有以原子方式进行操作的事实,并进行不必要的查找。两个线程可以同时通过第一次value == null检查。现在并不是真正的问题(除了Value会创建 2 秒,这很慢),但如果有人在第二次检查中添加 else 子句,就会出现错误value == null。这样也比较干净。
boolean foo(String key) {
Value value = map.putIfAbsent(key, new Value());
if (value == null) {
// do some stuff
return true;
}
else {
// do some other stuff
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
现在让我们解决创建速度慢的事实Value(听起来像是您在滥用构造函数,但无论如何)。
boolean foo(String key) {
final AtomicBoolean wasCreated = new AtomicBoolean(false);
final Value value = map.computeIfAbsent(key, k -> {
wasCreated.set(true);
return new Value();
});
if (wasCreated.get()) {
// do some stuff
return true;
}
else {
// do some other stuff
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
289 次 |
| 最近记录: |