LogOnJava/Vector and its fail-fast iterator

TIP : Vector 와 Iterator, Enumeration

java.util.Vector 클래스는 java.util.ArrayList와 비교되어 많이 사용되는 클래스이다.

흔히 자바 개발자는 Vector 클래스는 동기화된 ArrayList, ArrayList 클래스는 동기화되지 않은 Vector 클래스로 인식한다.

물론 틀리지 않았다.

그러면 Enumeration와 Iterator는? 흔히 Enumeration와 Iterator를 비교할 때에는 Enumeration 인터페이스는 메소드 이름들이 긴 Collection 이전 방식의 순차 인터페이스이고 Iterator 인터페이스는 메소드 이름들이 짧은 Collection 방식의 순차 인터페이스로 기억한다.

물론 틀리지 않았다.

Vector 클래스가 List 인터페이스를 구현하고 있으므로 iterator() 메소드를 지원한다. 물론 Enumeration 인터페이스를 제공하는 elements() 메소드도 지원한다.

그럼 iterator()의 결과인 Iterator와 elements()의 결과인 Enumeration 인터페이스는 기능이 완전히 동일한 것일까?

그렇지 않다는 것이다.

Vector에서 iterator() 메소드는 부모 클래스인 AbstractList의 것을 그대로 사용한다. 이 iterator() 메소드의 특징은 fail-fast라는 데 있다. JavaDoc API 문서를 보면 다음과 같이 iterator() 메소드에 대해 설명하고 있다.

 The Iterators returned by Vector's iterator and listIterator methods are fail-fast: if the Vector is structurally modified at any time after the Iterator is created, in any way except through the Iterator's own remove or add methods, the Iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the Iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future. The Enumerations returned by Vector's elements method are not fail-fast.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

이 말을 간단하게 설명하면, Vector 클래스의 iterator() 메소드의 리턴값으로 받은 Iterator 인터페이스를 사용하여 순차하는 도중, 해당 Iterator 객체의 remove나 add가 아닌 다른 방식에 의해 Vector 클래스에 변경이 일어나면 ConcurrentModificationException 이라는 런타임 예외가 발생한다는 것이다.

이것이 원하는 결과가 아니라면... Enumeration을 사용하면 된다.

특히 여러 개의 쓰레드가 Vector 객체를 순차하기도 하고, 수정하기도 할 때, fail-fast 방식의 런타임 예외가 원하는 결과가 아니라 조용히 진행되길 원한다면 옛날 방식 인터페이스인 Enumeration을 사용해야 한다.

last edited 2005-11-30 20:12:42 by YoonKyungKoo