Rav*_*eep 17 java concurrentmodification
以下Java代码ConcurrentModificationException按预期抛出:
public class Evil
{
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("lalala");
c.add("sososo");
c.add("ahaaha");
removeLalala(c);
System.err.println(c);
}
private static void removeLalala(Collection<String> c)
{
for (Iterator<String> i = c.iterator(); i.hasNext();) {
String s = i.next();
if(s.equals("lalala")) {
c.remove(s);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是下面的示例(仅在内容中有所不同)Collection执行时没有任何异常:
public class Evil {
public static void main(String[] args)
{
Collection<String> c = new ArrayList<String>();
c.add("lalala");
c.add("lalala");
removeLalala(c);
System.err.println(c);
}
private static void removeLalala(Collection<String> c) {
for (Iterator<String> i = c.iterator(); i.hasNext();) {
String s = i.next();
if(s.equals("lalala")) {
c.remove(s);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将打印输出"[lalala]".ConcurrentModificationException第一个例子的第二个例子为什么不抛出?
Jir*_*sek 22
因为迭代器的快速失败行为无法保证.
您将获得此异常,因为除非通过迭代器,否则在迭代时不能操作集合.
坏:
// we're using iterator
for (Iterator<String> i = c.iterator(); i.hasNext();) {
// here, the collection will check it hasn't been modified (in effort to fail fast)
String s = i.next();
if(s.equals("lalala")) {
// s is removed from the collection and the collection will take note it was modified
c.remove(s);
}
}
Run Code Online (Sandbox Code Playgroud)
好:
// we're using iterator
for (Iterator<String> i = c.iterator(); i.hasNext();) {
// here, the collection will check it hasn't been modified (in effort to fail fast)
String s = i.next();
if(s.equals("lalala")) {
// s is removed from the collection through iterator, so the iterator knows the collection changed and can resume the iteration
i.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
现在转到"为什么":在上面的代码中,注意如何执行修改检查 - 删除将集合标记为已修改,下一次迭代检查任何修改,如果检测到集合已更改则失败.另一个重要的事情是,ArrayList(不知道其他收藏品),并不能为您在修改hasNext().
因此,可能会发生两件奇怪的事情:
ArrayList.hasNext()实际上也会返回false,因为迭代器current index现在指向最后一个元素(前者倒数第二个).
请注意,这一切都与ArrayList的文档一致:
请注意,迭代器的故障快速行为无法得到保证,因为一般来说,在存在不同步的并发修改时,不可能做出任何硬性保证.失败快速迭代器会尽最大努力抛出ConcurrentModificationException.因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应该仅用于检测错误.
此问题提供了有关未执行并发修改检查的原因hasNext()以及仅在执行中执行的一些信息next().
| 归档时间: |
|
| 查看次数: |
1050 次 |
| 最近记录: |