According to http://download.oracle.com/javase/1.4.2/docs/api/java/util/Vector.html
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 unsync开发者_StackOverflow中文版hronized 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
Could you give me an example to validate the above set of statements ?Im still unclear with fail fast behaviour of vector's method Iterator and ListIterator.? Confused :-((
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
.
Here is an example:
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);
}
}
}
Output:
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)
The program does the following:
- Creates a Vector and gets an iterator
- Calls
next()
twice. - Modifies the vector (by removing the first element)
- Calls
next()
again (after the vector has been modified) - This causes a
ConcurrentModificationException
to be thrown.
Since Java's for-each loops rely on iterators these constructs may also throw ConcurrentModificationExceptions. The solution is to make a copy of the list before iterating (so you iterate over a copy) or to use for instance an CopyOnWriteArrayList
like this:
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);
}
}
}
Output:
lorem
ipsum
dolor
sit
A simple way to trigger a concurrent modification exception is
List<String> strings = new ArrayList<String>();
strings.add("a");
strings.add("b");
for(String s: strings)
strings.remove(s);
This triggers an exception because the collection is changed while iteration over the collection.
The reason the Iterator fails fast is to help you detect that a collection was modified concurrently (which these collections don't support) and help detect where the error occurred. If it didn't have this feature you could have subtle bugs which may not show a problem until much later in your code. (Making them much harder to race)
The newer concurrency collections handle concurrent modification differently and don't do this in general. They were introduced into core Java in 2004, i suggest you have a look at these newer collections.
BTW: Don't use Vector unless you have to.
Say you have a Vector of Integers containing 1-10 and you want to remove the odd numbers. You iterate over this list looking for odds and using the Iterators remove()
method. After this you have some code that of course assumes there are no odd numbers in the Vector. If another thread modifies the vector during this process, there might sometimes actually be an odd number (depending on the race condition), breaking the code that comes after. Perhaps it doesn't even break right away; maybe it doesn't cause a problem until hours or days later -- very hard to troubleshoot. This is what happens with the elements()
method.
Fail-fast means trying to detect this (potential) problem as soon as it occurs and sounding the alarm, which makes it much easier to troubleshoot. As soon as another thread is found to have modified the collection, an exception is thrown. This is what happens with the iterators.
The Iterators returned by iterator()
and listIterator()
actively watch for unexpected modifications to the underlying list. The Vector class (actually its parent AbstractList), increments a counter each time it is modified. When iterators for the Vector are created, they store a copy of the Vector's modification counter. Each time you call next()
or remove()
the Iterator compares it's stored value for the counter to the Vector's actual counter. If they differ, it throws a ConcurrentModificationException.
精彩评论