根据http://download.oracle.com/javase/1.4.2/docs/api/java/util/Vector.html
向量的迭代器和listIterator方法返回的迭代器是快速失败的:如果在创建iterator之后的任何时候对向量进行了结构上的修改,那么除了通过Iterator自己的remove或add方法,Iterator将抛出一个ConcurrentModificationException。因此,在并发修改的情况下,迭代器迅速而干净地失败,而不是在未来一个未定的时间冒着任意的、不确定的行为的风险。向量元素方法返回的数字不会失败。请注意,迭代器的快速失败行为不能保证,一般来说,在不同步并发修改的情况下不可能提供任何硬的保证。快速失败的迭代器在最大努力的基础上将ConcurrentModificationException抛出。因此,编写依赖于此异常的程序是错误的:迭代器的快速失败行为应该只用于检测bug。
,你能给我一个例子来验证上面的一组语句吗?我还不清楚向量的方法Iterator和ListIterator的快速失效行为。?困惑:-(
发布于 2010-12-18 19:01:17
--如果在创建Iterator之后的任何时候对向量进行结构修改,则除通过Iterator自己的remove或add方法外,Iterator将抛出一个
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)该方案做了以下工作:
twice.
next() next() (在向量已为modified)
ConcurrentModificationException。由于Java的for-每个循环依赖于迭代器,这些构造也可能抛出ConcurrentModificationExceptions。解决方案是在迭代之前创建列表的副本(因此您可以在副本上进行迭代),或者例如使用这样的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发布于 2010-12-18 19:02:05
触发并发修改异常的一种简单方法是
List<String> strings = new ArrayList<String>();
strings.add("a");
strings.add("b");
for(String s: strings)
strings.remove(s);这会触发异常,因为集合在集合上的迭代过程中会更改集合。
Iterator快速失败的原因是帮助您检测一个集合是并发修改的(这些集合不支持),并帮助检测错误发生的位置。如果它没有这个特性,那么您可能会有一些微妙的bug,这些bug可能直到您的代码后面很久才会出现问题。(使他们更难比赛)
较新的并发集合处理并发修改的方式不同,一般不会这样做。它们是在2004年引入核心Java的,我建议您看看这些新的集合。
顺便说一句:除非你必须使用向量,否则不要使用矢量。
发布于 2010-12-18 19:26:11
假设您有一个包含1-10的整数向量,并且要删除奇数。您在此列表上迭代,查找赔率,并使用迭代器remove()方法。在此之后,您有一些代码,当然,假设向量中没有奇数。如果另一个线程在此过程中修改向量,有时可能会出现奇数(取决于竞争条件),从而破坏后面的代码。也许它甚至不会马上崩溃;也许它直到几个小时或几天后才会产生问题--很难排除故障。这就是elements()方法所发生的事情。
快速故障意味着一旦出现这个(潜在的)问题并发出警报,这将使故障诊断变得容易得多。一旦发现另一个线程修改了集合,就会引发异常。迭代器就是这样发生的。
iterator()和listIterator()返回的迭代器积极监视对基础列表的意外修改。向量类(实际上是它的父AbstractList)每次修改计数器时都会增加一个计数器。当为向量创建迭代器时,它们会存储向量修改计数器的副本。每次调用next()或remove()时,Iterator都会将计数器的存储值与向量的实际计数器进行比较。如果它们不同,就会抛出一个ConcurrentModificationException。
https://stackoverflow.com/questions/4479554
复制相似问题