Search code examples
javajava.util.concurrentconcurrentmodification

List ConcurrentModificationException


I have the following code

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);
}

When I am executing the above, I am getting the following exception at 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)

How can I resolve this issue with usage of next or with iterator?

Edit 1

Code snippet where I am calling saveProjects

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

          myDAO.saveProjects(projectList);

     }
  projectList.clear();

Solution

  • From code

    for (Project persist: projectList) { 
         persist.setProjectId("K7890");
         persist.setName(fileName);
    
          myDAO.saveProjects(projectList); 
     }
    
    projectList.clear(); // <-- clear might cause to this Exception
    

    Reference

    Why do you get a ConcurrentModificationException when using an iterator?

    The java.util Collection classes are fail-fast, which means that if one thread changes a collection while another thread is traversing it through with an iterator the iterator.hasNext() or iterator.next() call will throw ConcurrentModificationException.

    Even the synchronized collection wrapper classes SynchronizedMap and SynchronizedList are only conditionally thread-safe, which means all individual operations are thread-safe but compound operations where flow of control depends on the results of previous operations may be subject to threading issues. (List myList = Collections.synchronizedList (myList) ! It may not work here)

    Solutions for multi-thread access situation

    Solution 1: You can convert your list to an array with list.toArray() and iterate on the array. This approach is not recommended if the list is large.

    Solution 2: You can lock the entire list while iterating by wrapping your code within a synchronized block. This approach adversely affects scalability of your application if it is highly concurrent.

    Solution 3: You can use the ConcurrentHashMap and CopyOnWriteArrayList classes, which provide much better scalability and the iterator returned by ConcurrentHashMap.iterator() will not throw ConcurrentModificationException while preserving thread-safety.

    Solution for single-thread access situation

    Use:

    it.remove();
    

    It removes the current object via the Iterator it which has a reference to your underlying collection list.

    Avoid:

    list.remove(myObject);