我有以下代码
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.AbstractList$Itr.checkForComodification(AbstractList.java:449) at java.util.AbstractList$Itr.next(AbstractList.java:420)的java.util.ConcurrentModificationException
如何使用next或迭代器来解决这个问题?
编辑1
调用saveProjects的代码段
projectList.add(proj);
for (Project persist: projectList) {
persist.setProjectId("K7890");
persist.setName(fileName);
myDAO.saveProjects(projectList);
}
projectList.clear();发布于 2013-10-27 19:57:03
从代码
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:您可以通过在同步块中包装代码来锁定整个列表。如果应用程序高度并发,则此方法会对其可伸缩性产生不利影响。
解决方案3:您可以使用ConcurrentHashMap和CopyOnWriteArrayList类,它们提供了更好的可伸缩性,ConcurrentHashMap.iterator()返回的迭代器不会在维护线程安全的同时抛出ConcurrentModificationException。
单线程访问情况的解决方案
使用:
it.remove();它通过Iterator it删除当前对象,Iterator list对基础集合list具有引用。
避免:
list.remove(myObject);发布于 2013-10-27 20:20:02
看起来很奇怪,我猜您是在迭代时在另一个线程中修改列表(List<Project> proj)吗?
因为您没有在您给我们的代码中以任何方式更改列表。
您可以尝试使用saveProjects列表的副本调用proj方法。
https://stackoverflow.com/questions/19622773
复制相似问题