根据http://download.oracle.com/javase/1.4.2/docs/api/java/util/Vector.html
Vector的回复迭代器 iterator和listIterator方法是 失败快速:如果Vector是 随时进行结构修改 在Iterator创建之后,任何一个 除了通过Iterator自己的方式 删除或添加方法,迭代器 会抛出一个 ConcurrentModificationException的。从而, 面对并发 修改,迭代器失败 快速而干净,而不是 冒着任意,不确定的风险 在一个不确定的时间的行为 未来。枚举返回 通过Vector的元素方法不是 快速失败的。请注意,失败快 迭代器的行为不可能 通常保证原样 说话,不可能做出任何努力 保证存在 不同步的并发 修改。失败快速的迭代器 抛出ConcurrentModificationException 尽力而为。因此,它 写一个程序是不对的 依赖于这个例外 正确性:失败的快速行为 迭代器应该只用于 检测错误
你能给我一个例子来验证上面的语句吗?我还不清楚vector的方法Iterator和ListIterator的快速行为失败。困惑: - ((
答案 0 :(得分:8)
如果在创建迭代器后的任何时候对Vector进行结构修改,除了通过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)
该计划执行以下操作:
next()
。next()
(修改了矢量后)ConcurrentModificationException
被抛出。由于Java的for-each循环依赖于迭代器,因此这些构造也可能抛出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
答案 1 :(得分:2)
触发并发修改异常的一种简单方法是
List<String> strings = new ArrayList<String>();
strings.add("a");
strings.add("b");
for(String s: strings)
strings.remove(s);
这会触发异常,因为在对集合进行迭代时会更改集合。
Iterator快速失败的原因是帮助您检测到并发修改了一个集合(这些集合不支持)并帮助检测错误发生的位置。如果它没有此功能,您可能会遇到一些细微的错误,这些错误可能会在您的代码中稍后出现问题。 (让他们更难以参加比赛)
较新的并发集合以不同方式处理并发修改,并且通常不执行此操作。他们在2004年被引入核心Java,我建议你看看这些新的系列。
BTW:除非必须,否则不要使用Vector。
答案 2 :(得分:1)
假设您有一个包含1-10的整数向量,并且您想删除奇数。您遍历此列表以查找赔率并使用迭代器remove()
方法。在此之后你有一些代码,当然假设Vector中没有奇数。如果另一个线程在此过程中修改了向量,有时可能实际上存在奇数(取决于竞争条件),从而破坏了之后的代码。也许它甚至没有立即破裂;也许它不会在几小时或几天后引起问题 - 很难排除故障。这就是elements()
方法所发生的情况。
快速失败意味着一旦发生并发出警报就会尝试检测此(潜在)问题,这样可以更容易地进行故障排除。一旦发现另一个线程修改了集合,就会抛出异常。这就是迭代器所发生的事情。
iterator()
和listIterator()
返回的迭代器主动监视对基础列表的意外修改。 Vector类(实际上是它的父AbstractList)在每次修改时递增一个计数器。当创建Vector的迭代器时,它们存储Vector的修改计数器的副本。每次调用next()
或remove()
时,迭代器都会将计数器的存储值与Vector的实际计数器进行比较。如果它们不同,则会抛出ConcurrentModificationException。