mit*_*shi 12 java concurrenthashmap
我正在尝试找到这些答案,但无法在Google或Java文档中理解(或确认)它.
我的实现看起来像这样:
Map<String, POJO> map = new ConcurrentHashMap<String, POJO>();
Run Code Online (Sandbox Code Playgroud)
如果我做
value1 = map.get(key1);
value1.setProp(prop);
Run Code Online (Sandbox Code Playgroud)
任何其他线程可能会覆盖.
现在,我在想如果我喜欢以下内容:它会是一个原子操作/换句话说,它会阻止key1段吗?
map.compute(key1, (key1, value1) -> { value1.setProp(prop) });
Run Code Online (Sandbox Code Playgroud)
Javadoc的compute功能
尝试计算指定键及其当前映射值的映射(如果没有当前映射,则为null).整个方法调用以原子方式执行.其他线程在此映射上的某些尝试更新操作可能在计算进行时被阻止,因此计算应该简短,并且不得尝试更新此Map的任何其他映射.
参考文献:
1. https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html 2. https://docs.oracle.com/javase/8/docs/api/java /util/concurrent/ConcurrentHashMap.html#compute-K-java.util.function.BiFunction-
对于我的最终实现,我做了类似这样的事情,因为所有线程共享NewMap,最后,我新的POJO列表
抽象数据类型
public class NewMap {
private Map<String, POJO> map;
private boolean isUpdatable;
void NewMap(){
isUpdatable = true;
map = new ConcurrentHashMap();
}
void putPOJOProp1(String key, Type value) throws ReadOnlyException{
map.compute(key, (k,v) -> {
if(!isUpdatable) throw new ReadOnlyException();
if(k == null){
POJO p = new POJO();
p.setProp1(value);
v = p;
} else {
v = v.setProp1(v)
}
});
}
void putPOJOProp2....
void putPOJOProp3....
List<POJO> getAll() {
isUpdatable = false;
List<POJO> pojos;
for(key: map.getKeys()) {
Pojo p = map.get(key);
p.setKey(key);
pojos.add(p);
}
return pojos;
}
}
Run Code Online (Sandbox Code Playgroud)
你困惑的两个不同的术语.
ConcurrentHashMap防止内部结构腐败,但不防止竞争条件.如果你想避免的只是数据损坏,那么使用ConcurrentHashMap是有效的.
但是从你的问题看来,你似乎在试图避免竞争条件.ConcurrentHashMap不以任何方式保护你免受他们的伤害.
为了更好地理解它,让我们看看以下示例:
Map<String, POJO> map = new ConcurrentHashMap<>();
ExecutorService pool = Executors.newWorkStealingPool(10);
for (int t = 0; t < 10; t++) {
pool.execute(() -> {
for (int i = 0; i < 100_000; i++) {
map.compute("A", (k, v) -> {
if (v == null) {
return new POJO();
}
v.a = ++v.a;
v.b = ++v.b;
return v;
});
}
});
}
pool.awaitTermination(5, TimeUnit.SECONDS);
System.out.println(map);
// With POJO like
class POJO {
// toString() here
Integer a = 1;
Integer b = 1;
}
Run Code Online (Sandbox Code Playgroud)
我们得到了{A=POJO{a=1000000, b=1000000}},所以我们的操作是线程安全的.如果这就是你想要的,你就没事了.
ConcurrentHashMap.compute的Javadoc 说明
整个方法调用以原子方式执行.
注意,通过比较,ConcurrentSkipListMap.compute它不是原子的.
更为紧凑的Alexey Soshin的答案是
Map<String, long[]> map = new ConcurrentSkipListMap<>();
map.put("A", new long[2]);
IntStream.range(0, 1_000_000)
.parallel()
.forEach(i -> map.compute("A", (k, v) -> {
v[0]++;
v[1]++;
return v;
}));
System.out.println(Arrays.toString(map.get("A")));
Run Code Online (Sandbox Code Playgroud)
打印像
[643553, 597254]
Run Code Online (Sandbox Code Playgroud)
cf HashMap产生类似的东西
[244786, 245993]
Run Code Online (Sandbox Code Playgroud)
但是,使用a ConcurrentHashMap并获得预期
[1000000, 1000000]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
399 次 |
| 最近记录: |