可以更改HashMap值的成员导致java.util.ConcurrentModificationException

时间:2017-02-09 05:43:59

标签: java exception hashmap concurrentmodification

以下代码抛出并发修改异常,异常所指向的行是for循环的第一行

private synchronized void updateAllCacheValues() {
        for (Map.Entry<Configurations, SalesConfiguration> entry : ConfigurationCache.entrySet()) {
            Configurations conf = entry.getKey();
            SalesConfiguration saleConfiguration = ConfigurationCache.get(conf);
            Map<String, String> newMap = generateKeyValueMapFromConfigurations(conf);
            lastLoadTimestamp = new Date();
            saleConfiguration.setMap(newMap, lastLoadTimestamp);
        }
        logger.debug("Successfully updated all cached configurations., cache size " + ConfigurationCache.size() + "LAST_LOAD_TIME" + lastLoadTimestamp);
    }

以下是异常追踪

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
at com.learning.java.daily.updateAllCacheValues(ConfigurationLoader.java:237)
at com.learning.java.daily.updateAllCacheValues.impl.ConfigurationLoader.loadConfigurations(ConfigurationLoader.java:156)

我无法猜出是什么导致了这个异常,因为我编写了一个示例测试,我在修改Map值的属性,但没有出现并发修改异常。

3 个答案:

答案 0 :(得分:1)

要回答标题中的问题:,修改HashMap中的值对象,而迭代条目集不能单独生成ConcurrentModificationException }。必须有其他事情发生。

generateKeyValueMapFromConfigurations()saleConfiguration.setMap()的调用是否可以修改地图?可能是你的ConfigurationCache可以被其他一些并发线程修改?我知道我只是猜测,这是我们用手头的信息做的最好的。

答案 1 :(得分:0)

我认为这条线是罪魁祸首。

saleConfiguration.setMap(newMap, lastLoadTimestamp);

字面上ConcurrentModificationException来自迭代它时更新地图条目。你能否请注释掉那一行并检查你是否再次获得例外?如果不是,则需要更改逻辑,以便在迭代它们时不更改映射条目。

答案 2 :(得分:0)

您正在迭代入口集。因此,在迭代时不允许修改入口集值。使用ConcurrentHashMap而不是HashMap。

这是分析。

我们可以修改键/值的属性。但是我们不能通过在迭代时向地图添加或删除元素来修改地图。假设一个地图有五个元素,当我们迭代它时,我们既不能添加元素来映射也不能从地图中删除元素。为此,我们应该使用ConcurrentHashMap。

希望现在更清楚。