【问题标题】:List ConcurrentModificationException列出 ConcurrentModificationException
【发布时间】:2013-11-06 12:22:30
【问题描述】:

我有以下代码

public void saveProjects(List<Project> proj) throws DatabaseException {
    for (Project listItems: proj) { // error here

        insertProjects(listItems);
    }
}

private void insertProjects(Project prj) throws DatabaseException {
    commitObjects(prj);
}

当我执行上述操作时,我在for (Project listItems: proj) { 收到以下异常

java.util.ConcurrentModificationException 在 java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449) 在 java.util.AbstractList$Itr.next(AbstractList.java:420)

如何使用 next 或 iterator 解决此问题?

编辑 1

我调用 saveProjects 的代码 sn-p

projectList.add(proj);
  for (Project persist: projectList) {
       persist.setProjectId("K7890");
       persist.setName(fileName);

          myDAO.saveProjects(projectList);

     }
  projectList.clear();

【问题讨论】:

  • 不确定投反对票的原因。这是一个合法且完整的问题。 1+
  • 我收回了。错字令人分心和误导。
  • @HovercraftFullOfEels 谢谢
  • commitObjects(prj) 是做什么的?它是否以某种方式修改了List&lt;Project&gt; proj
  • @HovercraftFullOfEels 我已经包含了 commitObjects 方法代码 sn-p。

标签: java java.util.concurrent concurrentmodification


【解决方案1】:

来自代码

for (Project persist: projectList) { 
     persist.setProjectId("K7890");
     persist.setName(fileName);

      myDAO.saveProjects(projectList); 
 }

projectList.clear(); // <-- clear might cause to this Exception

参考

为什么在使用迭代器时会出现 ConcurrentModificationException?

java.util Collection 类是快速失败的,这意味着如果一个线程更改集合,而另一个线程正在使用迭代器遍历它,iterator.hasNext()iterator.next() 调用将抛出ConcurrentModificationException

即使是同步集合包装类 SynchronizedMapSynchronizedList 也只是有条件的线程安全,这意味着所有单独的操作都是线程安全的,但控制流取决于先前操作结果的复合操作可能会受到线程问题。 (List myList = Collections.synchronizedList (myList)!这里可能不行)

多线程访问情况的解决方案

解决方案 1:您可以使用 list.toArray() 将列表转换为数组并迭代该数组。如果列表很大,不建议使用此方法。

解决方案 2:您可以在迭代时锁定整个列表,方法是将代码包装在同步块中。如果应用程序高度并发,这种方法会对应用程序的可扩展性产生不利影响。

解决方案 3:您可以使用 ConcurrentHashMapCopyOnWriteArrayList 类, 这提供了更好的可伸缩性,ConcurrentHashMap.iterator() 返回的迭代器不会抛出ConcurrentModificationException,同时保持线程安全。

单线程访问情况的解决方案

用途:

it.remove();

它通过迭代器it 删除当前对象,该迭代器引用了您的基础集合list

避免:

list.remove(myObject);

【讨论】:

  • Maxim,如果我从第二个中删除 for 循环,那么它将停止保存记录。
  • 如果你提交insertProjects(listItems);你仍然得到这个错误?
  • 你的意思是直接调用insertProjects(listItems);
  • 切换评论,例如 //insertProjects(listItems);也许连接会做一些事情。我不熟悉数据访问逻辑
  • 当我评论insertProjects(listItems); 时没有例外。
【解决方案2】:

看起来很奇怪,我的猜测是您在迭代时在另一个线程中修改了列表 (List&lt;Project&gt; proj)?

因为您不会以任何方式更改您提供给我们的代码中的列表。

您可以尝试使用proj 列表的副本调用saveProjects 方法。

【讨论】:

  • 这充其量只是一个评论(正如你已经做过的那样),而不是一个答案。
猜你喜欢
  • 1970-01-01
  • 2013-02-12
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多