빠른

2010-12-18 2 views
3

따르면에 http://download.oracle.com/javase/1.4.2/docs/api/java/util/Vector.html빠른

벡터의 iterator 및 listIterator 메소드에 의해 반환되는 반복자 있습니다 르파 : Vector의 구조적 후 언제든지 으로 변경 경우 Iterator 자체가 메서드를 제거하거나 추가하는 것을 제외하면 방법으로 Iterator가 작성되고 은 ConcurrentModificationException을 발생시킵니다. 따라서, 동시 변형 얼굴 는 반복자 미래에 예측할 수없는 시점에 예측할 수없는 위험 동작을 신속하고 완전히 실패보다는 . Vector의 elements 메서드에 의해 이 반환 된 열거 형은 fail-fast가 아닙니다. 그것은 일반적으로, 불가능 비동기의 동시 변경이있는 경우, 확실한 보증을 실시하는 말하기 입니다 반복자의 페이 르파 행동이 보장 할 수 없습니다. fail-fast iterators ConcreteModificationException 을 최선의 노력으로 throw합니다. 따라서 는 가 정확을 기하기 위해서이 예외에 의존하는 프로그램 쓰는 것은 잘못입니다 : 반복자의 페이 르파 스트의 동작은 버그

을 감지 에만 사용되어야한다 날 줄 수 위의 문장의 집합을 검증하는 예제? 벡터의 Iterator 및 ListIterator 메소드의 실패 빠른 동작에 대해서는 여전히 명확하지 않습니다.는 혼란 - Vector의 구조적 반복자의 작성 후에, Iterator 자체의 remove 이외 방법으로, 언제든지 수정 또는 메소드를 추가 할 경우 ((

답변

8

는, 반복자는 던질 것 ConcurrentModificationException

.

import java.util.*; 

public class Test { 

    public static void main(String[] args) { 
     List<String> strings = new Vector<String>(); 

     strings.add("lorem"); 
     strings.add("ipsum"); 
     strings.add("dolor"); 
     strings.add("sit"); 

     int i = 0; 

     Iterator<String> iter = strings.iterator(); 
     while (iter.hasNext()) { 
      System.out.println(iter.next()); 

      // Modify the list in the middle of iteration. 
      if (i++ == 1) 
       strings.remove(0); 
     } 
    } 
} 

출력 :

lorem 
ipsum 
Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) 
    at java.util.AbstractList$Itr.next(AbstractList.java:343) 
    at Test.main(Test.java:18) 
여기

은 일례이며

  1. 이 벡터를 작성 반복자에게
  2. 통화 next() 두 번을 가져옵니다

    이 프로그램은 다음을 수행합니다.

  3. 는 (벡터가 변형 된 후의)
  4. 이것은 슬로우하는 ConcurrentModificationException 발생 next() 다시 호출 (첫 번째 요소를 제거함으로써) 벡터를 수정.

Java의 for-each 루프는 반복자에 의존하기 때문에 이러한 구조는 ConcurrentModificationExceptions를 throw 할 수도 있습니다.이 솔루션은 반복 전에 목록의 복사본을 만드는 것입니다 (그래서 당신은 사본을 반복) 또는 예를 들어이 같은 CopyOnWriteArrayList 사용 :

import java.util.*; 
import java.util.concurrent.CopyOnWriteArrayList; 

public class Test { 

    public static void main(String[] args) { 
     List<String> strings = new CopyOnWriteArrayList<String>(); 

     strings.add("lorem"); 
     strings.add("ipsum"); 
     strings.add("dolor"); 
     strings.add("sit"); 

     int i = 0; 

     Iterator<String> iter = strings.iterator(); 
     while (iter.hasNext()) { 
      System.out.println(iter.next()); 

      // Modify the list in the middle of iteration. 
      if (i++ == 1) 
       strings.remove(0); 
     } 
    } 
} 

출력 :

lorem 
ipsum 
dolor 
sit 
+0

@ aioobe, 좋은 저녁, 왜 이렇게 벡터의 동작입니까? – Deepak

+0

Iterator는 벡터에 수행 한 작업을 알 수 없기 때문에. Iterator가'int currentIndex'로 구현되고, 이미 통과 한 인덱스에 요소를 추가한다고 가정하십시오. 그런 다음 반복자는'next()'에 대해 동일한 요소를 두 번 반환합니다. 이 fail-fast 메커니즘은 이러한 유형의 오류를 방지합니다. – aioobe

+0

@ aioobe, 도와 주셔서 감사합니다 – Deepak

2

간단한 방식을 동시 수정 예외를 트리거합니다.

List<String> strings = new ArrayList<String>(); 
strings.add("a"); 
strings.add("b"); 
for(String s: strings) 
    strings.remove(s); 

컬렉션을 반복하는 동안 컬렉션이 변경되기 때문에 예외가 트리거됩니다.

Iterator가 빠르게 실패하는 이유는 컬렉션이 동시에 수정되었다는 것을 (이러한 컬렉션이 지원하지 않는) 감지하여 오류가 발생한 위치를 찾는 데 도움이되기 때문입니다. 이 기능이 없다면 미묘한 버그가 생길 수 있습니다.이 버그는 나중에 코드에 나타날 때까지는 문제가되지 않을 수 있습니다. (경쟁을 더욱 어렵게 만듭니다)

최신 동시성 컬렉션은 동시 변경을 다르게 처리하므로 일반적으로 그렇게하지 않습니다. 그들은 2004 년에 핵심 Java에 도입되었으므로이 새로운 컬렉션을 살펴 보시기 바랍니다.

현재 : 사용하지 않는 한 Vector를 사용하지 마십시오.

+0

현재 : 벡터가 필요하지 않는 한 사용하지 마십시오 .-- 그 이유는 무엇입니까? – Deepak

+0

IMHO Vector/Hashtable/Enumeration은 1998 년 Java 1.2에서 대체 된 레거시 컬렉션 클래스입니다. 컬렉션 동시 사용을 위해이 기능을 지원하는 컬렉션이 2004 년 Java 5.0에 추가되었으므로 대신 이러한 컬렉션을 사용하는 것이 좋습니다. –

+0

코드도 보내 주셔서 감사합니다. – Deepak

1

1 ~ 10의 벡터가 있고 홀수를 제거하고 싶다고합시다. 이 목록을 반복하여 확률을 찾고 반복자 remove() 메서드를 사용하면됩니다. 이 코드 뒤에 벡터에 홀수가 없다고 가정합니다. 이 프로세스 중에 다른 스레드가 벡터를 수정하면 실제로는 홀수 (경쟁 조건에 따라 다름)가 발생하여 이후 코드가 깨질 수 있습니다. 아마도 그것은 즉시 중단되지 않습니다. 몇 시간 또는 며칠 후에 문제가 발생하지 않을 수도 있습니다. 문제를 해결하기가 매우 어렵습니다. 이것은 elements() 메소드에서 발생합니다.

오류가 발생하면 즉시 (잠재적 인) 문제를 감지하고 경고음을 울리므로 문제를 쉽게 해결할 수 있습니다. 콜렉션을 변경 한 thread가 발견되면 (자), 예외가 Throw됩니다. 이것은 반복자에서 발생합니다.

iterator()listIterator()에 의해 반환 된 반복자는 기본 목록에 예기치 않은 수정이 있는지를 감시합니다. Vector 클래스 (실제로는 부모 AbstractList)는 수정 될 때마다 카운터를 증가시킵니다. Vector의 반복자가 작성되면 벡터의 수정 카운터 사본이 저장됩니다. next() 또는 remove()을 호출 할 때마다 Iterator는 카운터의 저장된 값을 벡터의 실제 카운터와 비교합니다. 그것들이 다른 경우, ConcurrentModificationException를 Throw합니다.

+0

BTW : Vector 클래스의 메서드가 동기화됩니다. 그러나 반복기의 수명 동안 벡터가 잠기지 않으면 반복기는 스레드로부터 안전하지 않습니다. –

+0

감사합니다. @ 피터 - 수정 됨. 나는 더 많은주의를 기울여야했다. 나는 결코 Vector를 사용하지 않는다. –

+0

내 추천입니다. ;) –