Java. util. ConcurrentModificationException exception analysis

Source: Internet
Author: User
Tags concurrentmodificationexception
Java encounters java. util. ConcurrentModificationException when operating container classes such as ArrayList, HashMap, and TreeMap. Take ArrayList as an example. the following code snippet: importjava. util. ArrayList; importjava. util. Iterator;

Java encounters java. util. ConcurrentModificationException when operating container classes such as ArrayList, HashMap, and TreeMap. The following code snippet uses ArrayList as an example:

Import java. util. arrayList; import java. util. iterator; import java. util. list; import java. util. concurrent. copyOnWriteArrayList; public class Test {public static void main (String [] args) {List
 
  
StrList = new ArrayList
  
   
(); StrList. add ("string1"); strList. add ("string2"); strList. add ("string3"); strList. add ("string4"); strList. add ("string5"); strList. add ("string6"); // operation Method 1: while (Iterator); error Iterator
   
    
It = strList. iterator (); while (it. hasNext () {String s = it. next (); if ("string2 ". equals (s) {strList. remove (s) ;}/// Solution 1: Use the remove method of Iterator to delete elements. // operation Method 1: while (Iterator): no error is reported. // Iterator
    
     
It = strList. iterator (); // while (it. hasNext () {// String s = it. next (); // if ("string2 ". equals (s) {// it. remove (); //} // operation Method 2: foreach (Iterator); error // for (String s: strList) {// if ("string2 ". equals (s) {// strList. remove (s); //} // Solution 2: Do not use Iterator traversal, pay attention to index consistency // operation method 3: for (non-Iterator ); no error is reported. modify the index // for (int I = 0; I
     
      
Templist = new ArrayList
      
        (); // For (String s: strList) {// if (s. equals ("string2") {// templist. add (s); // view the removeAll source code, which uses Iterator to traverse // strList. removeAll (templist); // solution 4: Use thread-safe CopyOnWriteArrayList for deletion. // List
       
         StrList = new CopyOnWriteArrayList
        
          (); // StrList. add ("string1"); // strList. add ("string2"); // strList. add ("string3"); // strList. add ("string4"); // strList. add ("string5"); // strList. add ("string6"); // Iterator
         
           It = strList. iterator (); // while (it. hasNext () {// String s = it. next (); // if (s. equals ("string2") {// strList. remove (s );//}//}}}
         
        
       
      
     
    
   
  
 


After the code is executed, the following error is reported:

Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.ArrayList$Itr.checkForComodification(Unknown Source)at java.util.ArrayList$Itr.next(Unknown Source)at concurrentModificationException.Test.main(Test.java:21)

An error is reported in row 3, that is, it. next (). an error is reported when the iterator gets the next element. Find row 830th of java. util. ArrayList and see the source code of it. next (), as shown below:

        @SuppressWarnings("unchecked")        public E next() {            checkForComodification();            int i = cursor;            if (i >= size)                throw new NoSuchElementException();            Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length)                throw new ConcurrentModificationException();            cursor = i + 1;            return (E) elementData[lastRet = i];        }

The checkForComodification () method is called. the code is as follows:

        final void checkForComodification() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();        }

That is, compare whether modCount and expectedModCount are equal. ModCount is an attribute inherited by ArrayList from AbstractList. view the doc document of the modCount attribute. modCount indicates the number of times the list is structurally modified (structurally modified. Structurally modified is an operation that changes the number of elements in the list. add, addAll, remove, fastRemove, clear, removeRange, ensureCapacity, ensureCapacityInternal, ensureExplicitCapacity and other methods add modCount to 1, while batchRemove, removeAll, retainAll and other methods increase the value of modCount based on the number of deleted elements (removeAll and retainAll call the batchRemove implementation, the specific modCount modification algorithm still needs to be studied ).

Operation method 1 and operation method 2 in the first code snippet both adopt the iterator method. When the iterator method is used to obtain the Iterator object (or the ListItr object is obtained using listIterator), ArrayList $ Itr (inherited from javasactlist $ Itr) is actually returned ), this class is an internal class of ArrayList. This class has an expectedModCount field. when you call the next method of ArrayList $ Itr, check whether the value of modCount is equal to the value of expectedModCount (in fact, it will be checked when the next, remove, previous, set, add and other methods are called). if they are not equal, java will be thrown. util. concurrentModificationException exception. This phenomenon is called fail-fast in java doc.

Why is this exception thrown? The code shows that the add method is called six times, and the value of modCount is 6. when the iterator method is used to obtain the Iterator object, the value of modCount is assigned to expectedModCount, at the beginning, expectedModCount and modCount are equal. when the second element (index = 1) "string2" is iterated, the remove method is called because the if condition is true, when the remove method is called, the value of modCount is increased by 1. at this time, the value of modCount is 7, while the value of expectedModCount is not changed, when the next method of ArrayList $ Itr is called again, an exception is thrown because modeCount and expectedModCount are not equal.

This exception is not thrown when the if statement is written as if (s. equals ("string5"). why? In ArrayList $ Itr, a field named cursor is used to point to the element index to be operated during iteration. The initial value is 0. each call to the next method adds 1 to the field value, note that the element is first extracted from the set and then added with 1. When determining "string5", note that it is the second to last element. The value of these cursor is 5. if the element "string5" is removed, the List size is 5, when the hasNext method of ArrayList $ Itr is called to determine whether there is any next element, the result is determined based on whether the value of cursor is equal to the size. if the value is not equal, there is another element. at this time, the two values are exactly equal, if the next method is not executed, no exception is thrown. Therefore, when the last and last elements are deleted, no exception is thrown.

There are four solutions, just look at the first piece of code.


Reference link:

Http://blog.csdn.net/xtayfjpk/article/details/8451178

Only CopyOnWriteArrayList http://www.2cto.com/kf/201403/286536.html can be used in multi-thread scenarios


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.