2017-12-18 9 views
0

하나의 스레드가 반복 목록 일 때 다른 스레드가 기본 목록을 수정할 수 있고 우리는 ConcurrentModificationException (CME)을 얻을 수 없지만 ArrayList의 경우에는 CME를 받으십시오.CopyOnWriteArrayList (cowal)

하지만 다음 프로그램에는 하나의 스레드 (메인 스레드)가 있지만 여전히 CME를 얻고 있습니다. 왜요?

Iterator 때문입니까?

AL을 COWAL로 바꾸는 것보다 예외가 생기지 만 "D"요소가 없습니다. 왜요?

AL<String> l=new AL<>(); 
l.add("a"); 
l.add("b"); 
l.add("c"); 
Iterator<String> itr=l.iterator(); 
l.add("d"); 
while(itr.hasNext()) 
{ 
String s=itr.next(); 
Sop(s); 
} 
+0

나는 이미 했어요 ... "concurrent-collection" –

+0

마우스를 가져 가면 마우스가 JNet 것이 아닌 .Net 개념이라고 설명합니다. 예외를 얻는 이유는 이미 iterator를 얻은 후에 콜렉션 (AL)을 변경하기 때문입니다. 여기에 관련된 스레드의 수는 중요하지 않습니다. – StuartLC

+0

나는 ..didnt 공지를 .net 개념을 보여 주듯이 변경했다. –

답변

1

오류는 목록 구조를 수정하는

l.add("d"); 

라인 때문에 (추가 또는 요소를 제거) 반복자가 생성 된 후입니다.

내부적으로는 (ArrayList에의 추가 또는 제거) 상관 구조에서의 변화를 검사

itr.next(); 

호출되고 하나 개의 원소를 첨가하고, 따라서 어레이리스트의 크기가 변경이 있다는 것이 발견한다 .. 그것이 당신이 예외를 얻는 이유입니다. 당신이 반복자의 작성 이전 또는이 오류를 얻을 수 있습니다 반복자를 사용한 후 그 요소를 추가 할 경우

.. 아래

는의 코드는 ArrayList를 클래스에서) (다음;

 @SuppressWarnings("unchecked") 
    public E next() { 
     checkForComodification(); 
     ...... 
     return (E) elementData[lastRet = i]; 
    } 

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

ArrayList의 반복자는 디자인에 의해 르파 때문에 당신은 ConcurrentModificationException을 얻고있다. 즉, 일단 반복자가 생성되면 ArrayList(요소의 추가 또는 제거)으로 수정되면 ConcurrentModificationException이 반환됩니다. 당신이 예외 로그 문을 선택하면

, 그것은 때문에 수정을위한 반복자 검사 next() 방법 목록에서 반복자를 만드는 동안 사본을 IT modCount 변수를 사용하여 ArrayList의 크기의 checkForComodification() 메서드를 호출하여 itr.next() 방법으로 라인 String s=itr.next();에서 발생합니다.

이제 CopyOnWriteArrayList에 대한 이야기를 할 수 있습니다 당신은 CopyOnWriteArrayList 새에 내부 배열을 복사하여 구현되는 스레드 안전 세인 것을 모든 변경 조작이 추가, 제거 좋아하는 ArrayList, 세트이기 때문에이 예외가 점점되지 않는 경우 하나는 새로 생성 된 배열로 이전 배열을 대체합니다.

목록에서 iterator를 가져 오면 배열에 대한 참조가 저장되고 목록에 요소를 추가하면 목록의 배열이 완전히 새로워집니다. 그리고 반복자는 여전히 이전 배열을 가리키고 있습니다.

성명 l.add("d");에 새로 추가 된 요소가 콘솔에 인쇄되어 있지 않은 것을 확인했을 것입니다. 그러나 전체 목록을 인쇄하면됩니다.

List<String> l = new CopyOnWriteArrayList<>(); 
    l.add("a"); 
    l.add("b"); 
    l.add("c"); 
    Iterator<String> itr = l.iterator(); 
    l.add("d"); 
    while (itr.hasNext()) { 
     String s = itr.next(); 
     System.out.println(s); 
    } 
    System.out.println(l); 

출력은 생산은 다음과 같습니다 :이 도움이

a 
b 
c 
[a, b, c, d] 

희망

여기 CopyOnWriteArrayList와 샘플 코드입니다. 즐기십시오 :)