Every Java developer encountered ConcurrentModificationException in Java his/her life specially in early development days. How to avoid ConcurrentModificationException, how to overcome this exception either in multi-threaded or single-threaded environment.
1. overview of ConcurrentModificationException in Java?
Well, you must encountered this exception in developer life. java.util.ConcurrentModificationException in his/her life is usuall . You must have several questions in you mind: what is java.util.ConcurrentModificationException in Java? How to avoid java.util.ConcurrentModificationException? how to overcome java.util.ConcurrentModificationException exception either in multi-threaded or single-threaded environment.
For understanding concurrentModificationException you must know Fail-safe Vs Fail-fast iterator?
2. Why java.util.ConcurrentModificationException in Java?
- if two thread trying to modify one collection at same time. e.g. if one thread iterating and another removing.
- even in the same thread, remove List.remove() method while iterating using advance-for each loop.
- if trying to modify structure i.e. adding element to and removing element from fail-fast collection.
3. When to Throws java.util.ConcurrentModificationException
If you change the structure of fail-fast collection while iterating, it throws ConcurrentModificationException which I tried to demonstrate below. In below code base demonstrate while removing , but if you try to add it throws ConcurrentModificationException . internally it check counter flag is any modifying structure or not , if yes throws exception.
ConcurrentModificationExceptionExample.java
package com.mysoftkey.exception;
import java.util.ArrayList;
import java.util.List;
/**
* @author ranjeet Jha
*
*/
public class ConcurrentModificationExceptionExample {
/**
* @param args
*/
public static void main(String[] args) {
List frameworkList = new ArrayList();
// add values.
frameworkList.add("Spring");
frameworkList.add("Hibernate");
frameworkList.add("Struts");
for (String val : frameworkList) {
if ("Struts".equals(val)) {
frameworkList.remove(val);
}
}
// calling List's remove() method will throws java.util.ConcurrentModificationException while iterating
Iterator it = frameworkList.iterator();
while (it.hasNext()) {
String val = it.next();
if ("Struts".equals(val)) {
frameworkList.remove(val);
}
}
}
Console output with ConcurrentModificationException
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at com.mysoftkey.exception.ConcurrentModificationExceptionDemo.main(ConcurrentModificationExceptionDemo.java:26)
NOTE: If you want to go into more details of , how Iterator checks for the structure modification, You can lookinto java.util.AbstractList class where you can find an int variable modCount. modCount is used for the number of times list size has been changed. modCount value is used in every next() call to check for any modifications in a function checkForComodification().
3. How to use iterator.remove() method to avoid ConcurrentModificationException?
Either you use fail-safe collection to avoid ConcurrentModificationException or use Concurrent collection: ConcurrentHasMap, CopyOnArrayList, ListIterator. If you want to know about what is fail-fast and fail-safe collection, you can visit my post.
package com.mysoftkey.exception;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author ranjeet Jha
*
*/
public class ConcurrentModificationExceptionDemo {
/**
* @param args
*/
public static void main(String[] args) {
List frameworkList = new ArrayList();
// following code will not throws ConcurrentModificationException
Iterator itr = frameworkList.iterator();
while (itr.hasNext()) {
String val = itr.next();
if ("Struts".equals(val)) {
// Use Iterator's remove() method will throws java.util.ConcurrentModificationException
itr.remove();
}
}
}
}
4. How to avoid in multi-threaded environment?
Everyone in java must have upgraded at least jdk 5, if so then use concurrent collections class.
- use
ConcurrentHashMapandCopyOnWriteArrayListclasses, if using jdk 5 or higher version. - Use conversion of List to arrays, if collection size is small probably 100 or less. In larger collection impact performance.
- You can use synchronized block, but this will not help much in multi-threaded environment.
Multi-threadedIteratorExample.java
package com.mysoftkey.exception;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author ranjeet
*
*/
public class ConcurrentModificationExceptionExample {
public static void main(String[] args) {
System.out.println("=============== ConcurrentHashMap ==========================");
List frameworkList = new CopyOnWriteArrayList();
// add values.
frameworkList.add("Spring");
frameworkList.add("Hibernate");
frameworkList.add("Struts");
Iterator it = frameworkList.iterator();
while(it.hasNext()){
String value = it.next();
System.out.println("List Value:"+value);
if(value.equals("3")){
frameworkList.remove("Struts");
frameworkList.add("WebServices");
}
}
System.out.println("List Size:" + frameworkList.size());
System.out.println("=============== ConcurrentHashMap ==========================");
Map myMap = new ConcurrentHashMap();
myMap.put("1", "One");
myMap.put("2", "Two");
Iterator it1 = myMap.keySet().iterator();
while (it1.hasNext()) {
String key = it1.next();
System.out.println("Map Value:" + myMap.get(key));
if (key.equals("1")) {
myMap.remove("1");
myMap.put("100", "Hundres");
}
}
System.out.println("Map Size:" + myMap.size());
}
}
List Value:Spring List Value:Hibernate List Value:Struts List Size:3 =============== ConcurrentHashMap ========================== Map Value:One Map Value:Two Map Size:2
5. How to avoid ConcurrentModificationException in single-threaded Environment
if you trying to remove element from List while iterating.
Use Iterator’s remove() method if removing
// following code will not throws ConcurrentModificationException Iteratoritr = frameworkList.iterator(); while (itr.hasNext()) { String val = itr.next(); if ("Struts".equals(val)) { // calling Iterator's remove() method will throws java.util.ConcurrentModificationException itr.remove(); } }
Use classic/typical for loop while conditional remove.
for (int i = 0; i < frameworkList.size(); i++) {
String val = frameworkList.get(i);
System.out.println(val);
if ("Struts".equals(val)) {
frameworkList.remove(val);
}
}
6. Similar Posts
7. Reference
for more details visit Oracle Java Site
I hope, you enjoyed this post about ConcurrentModificationException in java. You can visit Core Java tutorial for more example blog post.
Write your comment if would like this post.