java 집합이 Concurrent Modification Exception을 일으키는 원인 분석

3244 단어
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 list = new ArrayList();
		list.add("map");
		list.add("key");
		list.add("jmey");
		Iterator iterator = list.iterator();
		while(iterator.hasNext()){
			list.add("bool");
			String val = iterator.next();
			System.out.println("values is:"+val);
		}
	}
}

컬렉션 반복자를 작성할 때 Itr 객체로 돌아가기
public Iterator iterator() {
        return new Itr();
}

교체기의next () 또는remove () 방법을 호출합니다
private class Itr implements Iterator {
        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개가 추가됨)
원소를 가져온 후 교체기를 직접 가져옵니다. 따라서 다음에 next () 검사를 실행하면expectedModCount가modCount와 같지 않아서 던집니다.
ConcurrentModificationException, 분석한 결과 교체기가 집합 요소를 옮겨다닐 때 집합 요소를 바꾸면 이 이상을 일으킬 수 있음을 알 수 있습니다.이 상황은 여러 줄에서 읽기와 쓰기가 동시에 발생합니다
ArrayList 하나가 이 이상을 일으킬 수도 있습니다.

좋은 웹페이지 즐겨찾기