java集合遍历引起ConcurrentModificationException的原因分析

引发ConcurrentModificationException的代码:

package test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ConcurrentModificationExceptionDemo {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("map");
		list.add("key");
		list.add("jmey");
		Iterator<String> iterator = list.iterator();
		while(iterator.hasNext()){
			list.add("bool");
			String val = iterator.next();
			System.out.println("values is:"+val);
		}
	}
}

创建集合迭代器时,返回Itr对象:

public Iterator<E> iterator() {
        return new Itr();
}

调用迭代器的next()或remove()方法
private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size;
        }

        @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];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

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

从代码中看出会首先执行checkForComodification()方法,该方法如下:

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


首先会检查modCount和expectedModCount是否相等,如果不等则抛出ConcurrentModificationException,而expectedModCount在创建
迭代器的时候由modCount赋值,在代码中可看到。而modCount则是记录集合改动的元素个数,在集合中元素变动的时候,该值会相应的
发生改动。

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

在上述迭代器遍历集合元素时先执行了list.add("bool")此时modCount变为4,而expectedModCount则为3(因集合添加了3个
元素后直接获取迭代器所以为3),因此在后续执行next()检查expectedModCount不等于modCount,从而抛出
ConcurrentModificationException,分析后得知:迭代器在遍历集合元素时,改变集合元素会引发该异常。此情况在多线并发读写同
一个ArrayList也可能引发该异常.

猜你喜欢

转载自blog.csdn.net/javajxz008/article/details/53546282
今日推荐