避免TreeMap ConcurrentModificationException?

时间:2012-12-18 06:34:23

标签: java treemap concurrentmodification

我正在调用返回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

5 个答案:

答案 0 :(得分:14)

请注意,如果您使用的是迭代器,Collections.synchronizedMap 永远不会保护您免受并发修改。此外,除非您从多个线程访问Map,否则创建同步映射是无用的。 本地范围的集合和未传递给其他线程的变量不需要synchronized

我的猜测是,在您遗漏的代码中,您正在迭代Map.entrySetMap.keySetMap.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)
}