2

java.util.ConcurrentModificationException在这种方法上得到以下信息

private AtomicReference<HashMap<String, Logger>> transactionLoggerMap = new AtomicReference<HashMap<String,Logger>>();

public void rolloutFile() {

    // Get all the loggers and fire a temp log line.
    Set<String> transactionLoggerSet = (Set<String>) transactionLoggerMap.get().keySet();
    Iterator<String> transactionLoggerSetIter = transactionLoggerSet.iterator();
    while(transactionLoggerSetIter.hasNext()){
        String key = (String) transactionLoggerSetIter.next();
        Logger txnLogger = transactionLoggerMap.get().get(key);
        localLogger.trace("About to do timer task rollover:");
        txnLogger.info(DataTransformerConstants.IGNORE_MESSAGE);
    }
}

请建议,如果我使用的是 Atomic Reference,我如何获得一个 como?

4

4 回答 4

9

AConcurrentModificationException表示您已在迭代器之外修改了集合。我在你的循环中没有看到任何修改,所以我假设transactionLoggerMap在你迭代它的同时还有另一个线程也在添加或删除。

即使你把它包裹在一个 中AtomicReference,你仍然不能有两个线程同时对同一个非同步集合进行更改。 AtomicReference不会同步正在包装的对象——它只是为您提供了一种以原子方式获取和设置该引用的方法。

您将需要通过使用该类或使用该方法ConcurrentHashMap包装您的方法来使其成为同步集合。HashMapCollections.synchronizedMap(map)

于 2012-05-18T19:16:07.260 回答
1

因为您没有在迭代期间防止并发修改。原子参考仅确保您获得地图(及其内容)。

于 2012-05-18T19:15:51.847 回答
1

也许您可以考虑迭代集合的本地副本而不是同一个集合。这将是一种简单的方法,可以确保您的收藏在循环时不会被修改。建议在多线程环境中使用不可变对象,您可以免费防止此类问题。

希望能帮助到你。

于 2012-05-18T19:19:16.173 回答
0

删除多余的 Set<String> transactionLoggerSet = (Set<String>) transactionLoggerMap.get().keySet(); 当您在地图上迭代时,您仍然必须使用同步。SynchronizedMap 保证其 API 方法的一致性。其余的,您需要进行客户端同步

于 2012-05-20T18:51:35.437 回答