我正在调用返回TreeMap
实例的函数,而在调用代码中我想修改TreeMap
。但是,我收到ConcurrentModificationException
。
这是我的代码:
public Map<String, String> function1() {
Map<String, String> key_values = Collections.synchronizedMap(new TreeMap<String, String>());
// all key_values.put() goes here
return key_values;
}
我的主叫代码是:
Map<String, String> key_values =Collections.synchronizedMap(Classname.function1());
//here key_values.put() giving ConcurrentModificationException
答案 0 :(得分:14)
请注意,如果您使用的是迭代器,Collections.synchronizedMap
永远不会保护您免受并发修改。此外,除非您从多个线程访问Map
,否则创建同步映射是无用的。 本地范围的集合和未传递给其他线程的变量不需要synchronized
。
我的猜测是,在您遗漏的代码中,您正在迭代Map.entrySet
,Map.keySet
或Map.values
中的一个,并调用put
在迭代期间(在for
循环内)。使用您显示的代码,这是唯一可能发生的方式。
答案 1 :(得分:5)
如果您使用ConcurrentSkipListMap,则可以更快,并且不会出现此问题。
public NavigableMap<String, String> function1() {
NavigableMap<String, String> key_values = new ConcurrentSkipListMap<String, String>();
// all key_values.put() goes here
return key_values;
}
如果您不需要排序密钥,可以使用ConcurrentHashMap。
答案 2 :(得分:1)
您似乎正在获取同步地图的同步地图。如果我用它的内容(简化)替换对function1()的调用,我们有:
Map<String, String> key_values =Collections.synchronizedMap(Collections.synchronizedMap( new TreeMap<String, String>()));
我认为您的致电热线应更改为:
Map<String, String> key_values = Classname.function1();
答案 3 :(得分:1)
您正在寻找同步MAP,因此我假设您正在处理多线程应用。在这种情况下,如果要使用迭代器,则必须同步MAP的块。
/*This reference will give error if you update the map after synchronizing values.*/
Map<String, String> values =Collections.synchronizedMap(function1());
/*This reference will not give error if you update the map after synchronizing values */
Map<String, String> values = Collections.synchronizedMap(new TreeMap<String, String>());
synchronized (values)
{
Iterator it = values.entrySet().iterator();
while(it.hasNext())
{
it.next() ;
// You can update the map here.
}
}
更新:
实际上在你的情况下,考虑到你是两次包装MAP的错误,即使使用synchronized块也会在while循环中修改它会产生CM异常,因为你无法同步在正在进行udpated的原始MAP对象上。
答案 4 :(得分:0)
这就是我提出ConcurrentModificationException
的过程:
TreeMap<Integer, Integer> map = new TreeMap<>();
for (Integer i : map.keySet()) {
map.remove(i)
}
这是我为修复异常而使用的相同功能的方法:
TreeMap<Integer, Integer> map = new TreeMap<>();
// I would not recommend this in production as it will create multiple
// copies of map
for (Integer i : new HashMap<>(integers).keySet()) {
map.remove(i)
}