Iterator之java.util.ConcurrentModificationException

  在运行以下代码时,会报java.util.ConcurrentModificationException异常,

 public class Demo {
  public static void main(String[] args) {
   List list = new LinkedList();
   list.add("1");
   list.add("#");
   list.add("2");
   list.add("#");
   list.add("3");
   list.add("#");
   list.add("4");
   Iterator it = list.iterator();
   while(it.hasNext()){
    String element = (String)it.next();
    if("#".equals(element)){
     list.remove(element);
    }
   }
  }
 }

究其原因以及查阅各方资料整理如下:

从API中可以看到List等Collection的实现并没有同步化,如果在多线程应用程序中出现同时访问,而且出现修改操作的时候都要求外部操作同步化;调用Iterator操作获得的Iterator对象在多线程修改Set的时候也自动失效,并抛出java.util.ConcurrentModificationException。这种实现机制是fail-fast,对外部的修改并不能提供任何保证。
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
  所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。List、Set等是动态的、可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator自己就迷失了方向。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。本例最后的解决方法是使用it.remove();

上一篇:crm踩坑记(二)


下一篇:iOS自动化打包上传的踩坑记