Java 并发修改异常

Java 并发修改异常,java,multithreading,concurrency,Java,Multithreading,Concurrency,我在这个方法上得到了以下java.util.ConcurrentModificationException private AtomicReference<HashMap<String, Logger>> transactionLoggerMap = new AtomicReference<HashMap<String,Logger>>(); public void rolloutFile() { // Get all the logg

我在这个方法上得到了以下
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);
    }
}
private AtomicReference transactionLoggerMap=new AtomicReference();
公共无效卷展文件(){
//把所有的伐木工人都找来,开一条临时记录线。
Set transactionLoggerSet=(Set)transactionLoggerMap.get().keySet();
迭代器transactionLoggerSetIter=transactionLoggerSet.Iterator();
while(transactionLoggerSetIter.hasNext()){
字符串键=(字符串)transactionLoggerSetIter.next();
记录器txnLogger=transactionLoggerMap.get().get(键);
trace(“即将执行计时器任务滚动:”;
txnLogger.info(DataTransformerConstants.IGNORE_消息);
}
}

请建议,如果我使用的是原子引用,我如何获得一个como?

,因为在迭代过程中,您没有防止并发修改。原子引用仅确保您获得映射(及其内容)。

A
ConcurrentModificationException
表示您已在迭代器之外修改了集合。我没有看到您的循环中有任何修改,因此我假设有另一个线程也在对
transactionLoggerMap
进行迭代的同时添加或删除它

即使将其包装在一个
原子引用中
,也不能让两个线程同时对同一个未同步的集合进行更改
AtomicReference
不会同步它正在包装的对象——它只是提供了一种以原子方式获取和设置该引用的方法


您需要使用“<代码> > CONCURNEASHMAP 类,或者使用<代码>集合收集您的<代码> HashMap <代码>。同步化映射(MAP)< /C>方法> < /P> < P>,您可以考虑在集合的本地副本上重复而不是同一个集合。这将是一个简单的方法,以确保你的收集不会被修改,而你在它的循环。建议在多线程环境中使用不可变对象,并免费防止此类问题

希望有帮助。

删除多余的
Set transactionLoggerSet=(Set)transactionLoggerMap.get().keySet()

在对映射进行迭代时,仍然必须使用同步。SynchronizedMap保证其API方法的一致性。对于其余部分,您将需要执行客户端同步

这完全正确,但在这个特定问题的上下文中可能是错误的,因为
get
调用可能正在更改映射的结构。更多信息:OP讨论的是一个
HashMap
,它不是一个访问有序的map@paranoid,而是一个很好的观点。