Wednesday 26 October 2016

Java Source World: ConcurrentModificationException when using an iterator

ConcurrentModificationException when using an iterator | Java Source World

                                                                                                               Java Source World A Java quick reference blog



How to avoid concurrent modification exception in java


Problem: 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.





package com.javaconcept.collections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class ConcurrentModification {
      public static void main(String[] args) {
            Collection<String> myCollection = new ArrayList<String>(10);
            myCollection.add("123");
            myCollection.add("456");
            myCollection.add("789");
            for (Iterator it = myCollection.iterator(); it.hasNext();) {
            String myObject = (String)it.next();
            System.out.println(myObject);
            myCollection.remove(myObject); //can throw ConcurrentModificationException in single as
            //well as multi-thread access situations.
            }

      }
}

Solutions 1-3: 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: If you are using JDK 1.5 then 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 4: for single-thread access situation:
Use:
it.remove(); // removes the current object via the Iterator “it” which has a reference to
// your underlying collection “myCollection”. Also can use solutions 1-3.

Avoid:
myCollection.remove(myObject); // avoid by-passing the Iterator. When it.next() is called, can throw the exception // ConcurrentModificationException

Note: If you had used any Object to Relational (OR) mapping frameworks like Hibernate, you may have encountered this exception “ConcurrentModificationException” when you tried to remove an object from a collection such as a java.util Set with the intention of deleting that object from the underlying database. This exception is not caused by Hibernate but rather caused by your java.util.Iterator (i.e. due to your it.next() call). You can use one of the solutions given above.



Other posts you may like:

How HashMap works in Java
Equals() and Hashcode() in java
Serialization in java

                                                                                                                Java Source World A Java quick reference blog



No comments:

Post a Comment