列出ConcurrentModificationException

时间:2013-10-27 19:56:11

标签: java java.util.concurrent concurrentmodification

我有以下代码

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       at java.util.AbstractList $ Itr.checkForComodification(AbstractList.java:449)       在java.util.AbstractList $ Itr.next(AbstractList.java:420)

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

编辑1

我正在调用saveProjects的代码片段

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

          myDAO.saveProjects(projectList);

     }
  projectList.clear();

2 个答案:

答案 0 :(得分:6)

来自代码

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()调用将抛出{ {1}}。

即使是同步的集合包装类ConcurrentModificationExceptionSynchronizedMap也只是有条件地线程安全的,这意味着所有单独的操作都是线程安全的,但复合操作的控制流程取决于先前操作的结果可能会受到线程问题的影响。 (SynchronizedList!这可能不起作用)

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

解决方案1 ​​:您可以将列表转换为List myList = Collections.synchronizedList (myList)的数组并迭代数组。如果列表很大,则不建议使用此方法。

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

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

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

使用:

ConcurrentModificationException

它通过Iterator it.remove(); 删除当前对象,该Iterator具有对基础集合it的引用。

避免:

list

答案 1 :(得分:1)

看起来很奇怪,我的猜测是你在迭代它时修改另一个线程中的列表(List<Project> proj)?

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

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