我有以下代码
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) at java.util.AbstractList$Itr.next(AbstractList.java:420)
如何使用 next 或迭代器解决此问题?
编辑 1
我调用 saveProjects 的代码片段
projectList.add(proj);
for (Project persist: projectList) {
persist.setProjectId("K7890");
persist.setName(fileName);
myDAO.saveProjects(projectList);
}
projectList.clear();
最佳答案
来自代码
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
。
即使是同步集合包装类 SynchronizedMap
和 SynchronizedList
也只是有条件的线程安全的,这意味着所有单独的操作都是线程安全的,但复合操作是控制流依赖的先前操作的结果可能会受到线程问题的影响。 (List myList = Collections.synchronizedList (myList)
!它可能在这里不起作用)
多线程访问情况的解决方案
解决方案 1:您可以使用 list.toArray()
将列表转换为数组并迭代该数组。如果列表很大,不推荐使用这种方法。
解决方案 2:您可以通过将代码包装在同步块(synchronized block)中来在迭代时锁定整个列表。如果它是高度并发的,这种方法会对应用程序的可扩展性产生不利影响。
解决方案 3:您可以使用 ConcurrentHashMap
和 CopyOnWriteArrayList
类,
它提供了更好的可扩展性,ConcurrentHashMap.iterator()
返回的迭代器不会抛出 ConcurrentModificationException
,同时保持线程安全。
单线程访问情况的解决方案
使用:
it.remove();
它通过迭代器 it
删除当前对象,该迭代器引用了您的基础集合 list
。
避免:
list.remove(myObject);
关于java - 列出 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19622773/