【发布时间】:2017-09-09 09:17:09
【问题描述】:
如果我迭代标准 HashMap 并尝试在迭代时向其中添加元素,我会得到 ConcurrentModificationException。
所以我尝试了一个允许并发添加的 HashMap:
ConcurrentHashMap<String, Integer> cMap = new ConcurrentHashMap<>();
cMap.put("one", 1);
cMap.forEach((key, value) -> cMap.put(key + key, value + value));
System.out.println(cMap);
但是,生成的地图有点奇怪:
{oneoneoneoneoneoneoneone=8, one=1, oneone=2, oneoneoneone=4}
如果将密钥更改为 zx (cMap.put("zx", 1)),现在的结果是:
{zxzx=2, zx=1}
问题:
1) 为什么会这样?两个并发操作(迭代和添加)不应冲突。
2) 不一致如何解决?
与集合相反,在迭代字符串的字符时更改字符串时,不会遇到此问题:
String str = scanner.next();
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i) == str.charAt(i-1)) {
str = str.substring(0, i-1) + str.substring(i+1);
i = 0;
}
}
if (str.length() == 0) {
System.out.println("Empty String");
} else {
System.out.println (str);
}
}
请注意,在上述循环中,源字符串实际上并未更改,而是重新分配,因为字符串是不可变的,无法修改。
上面的代码运行良好且始终如一。这是为什么字符串是线程安全的一个例子吗?
【问题讨论】:
-
我知道,我看过那个例子somewhere...
-
@Holger 你在一个本地 Java 组中被引用了你在那里制作的那些 cmets(导致
OOM),我们有时在这里做 :) 再次阅读它真是太棒了
标签: java string multithreading collections concurrency