LinkedHashSet迭代时的java.util.ConcurrentModificationExcepti
请帮助我理解我得到的错误:
private void replayHistory() { synchronized (alarmsHistory) { for (AlarmEvent alarmEvent : alarmsHistory) { LOG.error("replayHistory " + alarmEvent.type + " " + alarmEvent.source); sendNotification(alarmEvent.type,alarmEvent.source,alarmEvent.description,alarmEvent.clearOnOtherStations,alarmEvent.forceClearOnOtherStations); } } } 以及向其添加元素的方法 private void addToAlarmsHistory(AlarmEvent alarmEvent) { synchronized (alarmsHistory) { LOG.error("addToAlarmsHistory " + alarmEvent.type + " " + alarmEvent.source); alarmsHistory.add(alarmEvent); } } 两种方法和Set private volatile Set< AlarmEvent> alarmsHistory = new LinkedHashSet< AlarmEvent>(); 定义于 JmxGwReloadThread扩展了Thread类 这是一个内在的阶级 AlarmManager类 有方法 private void addToReplayHistory(AlarmEvent alarmEvent) { if ((jmxThread != null) && (jmxThread.isAlive())) { jmxThread.addToAlarmsHistory(alarmEvent); } } 这是由不同的接口调用(无法确定何时和多久) 在某些时候,JmxThread启动并调用replayHistory方法 抛出java.util.ConcurrentModificationException,root来自 for (AlarmEvent alarmEvent : alarmsHistory) { 该代码可以尝试将一个元素添加到alarmsHistory和interator时 java.util.ConcurrentModificationException at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:390) at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:401) at AlarmManager$JmxGwReloadThread.replayHistory(AlarmManager.java:568) at AlarmManager$JmxGwReloadThread.run(AlarmManager.java:532) 在调用nextEntry时抛出异常,但不应该同步阻止这样的问题吗? 日志显示同步不起作用 – replayHistory应该遍历其所有元素(我可以确定它的多个单个HEARTBEAT_INFO FM),但它被addToReplayHistory调用中断. 2013-07-11 11:58:33,951 Thread-280 ERROR AlarmManager$JmxGwReloadThread.replayHistory(AlarmManager.java:570) - replayHistory HEARTBEAT_INFO FM 2013-07-11 11:58:33,951 Thread-280 ERROR AlarmManager$JmxGwReloadThread.addToAlarmsHistory(AlarmManager.java:550) - addToAlarmsHistory HEARTBEAT_INFO FM 2013-07-11 11:58:33,952 Thread-280 ERROR Log4jConfigurator$UncaughtExceptionHandler.uncaughtException(Log4jConfigurator.java:253) - Detected uncaught exception in thread: Thread-280 解决方法
OP(可能是大多数人)应该注意的一件事:
ConcurrentModificationException与多线程无关. 虽然多线程使其更容易发生,但这个问题的核心与多线程无关. 这主要是由场景造成的, >从集合中获取迭代器, 当然,并非所有集合都有这样的行为,例如ConcurrentHashMap的. “结构修改”的定义也因不同的集合而不同. 这意味着,即使我只有一个帖子,如果我做的话: List<String> strings = new ArrayList<String>(); //.... for (String s: strings) { // iterating through the collection strings.add("x"); // structurally modifying the collection } 我将得到ConcurrentModificationException,即使它发生在单线程中. 根据您的要求或问题,有不同的方法可以解决问题.例如 >如果仅仅是由于多线程访问,适当的同步访问可以是一种解决方案 鉴于您的代码似乎在alarmHistory上具有正确的同步,您需要检查两个方向 > sendNotification()中是否有任何可能的alarmHistory修改?例如,在alarmHistory中添加或删除?>是否有其他可能的不同步访问alarmHistory可能会修改结构? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |