Iterator的fail-fast

   关于Iterator的fail-fast比较完整的解释请参考jdk中在Vector,ArrayList等具体实现时的相关描述:这里有一个比较清楚的翻译:

 * Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,
 * 当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照
 * fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
 *
 * 所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象,
 *Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
 *

 

     这里举一些列子进行分析:

    1).当正在使用Iterator时,如果再使用Collection的add,remove或者其他的Iterator操作,将会抛出异常,java代码如下:

  1:      Collection c = new ArrayList();

  2:     Collection1.fill(c,1);
  3:      Collection1.print(c);
  4:      Iterator iterator_c = c.iterator();

  5:     Iterator iterator_c2 = c.iterator();

  6:     for(;iterator_c.hasNext();){
  7:         int i = (Integer)iterator_c.next();
  8:        System.out.println(i);
 
  9:        c.remove(i);
            //iterator_c.remove();

  10:         if(iterator_c2.hasNext()){
                iterator_c2.next();
                iterator_c2.remove();
           }
      }

      在第9行这里,使用iterator的同时又使用了Collection自带的c.remove()方法,抛出ConcurrentModificationException 异常;第十行使用了另外一个同属于c的Iterator,同样会抛出异常;

  2):不同线程的迭代器操作(代码如下):

       a.不同线程操作同一个collection的不同迭代器,或者一个操作迭代器,另一个操作collection;抛出异常,道理同上;

       b.一个线程操作collection的迭代器,另外一个线程操作System.out.println(c);抛出异常,原因是在Collection.toString()中使用迭代器显示,本质道理同1);  

        c.AbstractList,abstractCollection中的addAll,removeAll方法都是用迭代器实现的;但是arrayList等容器重新实现了addAll(),也就是说 针对arraylist,linkedList如果你同时或者不同线程中使用了同一个对象的add和addAll方法.就不会出现异常;

           但是,如果你本质上同时使用了add和removeAll(c),则会抛出异常.

               

 总之,请确认你使用Iterator时本线程和其他线程中没有再操作该collection,如果不能避免这种情况,请换用其他的替代方案;

  代码示例:

      public class ThreadIterTest {
 List a  = new ArrayList();
 List b = new ArrayList();
 {
    for(int i=0;i<1000000;i++){
     a.add("a");
    }
  
 }

 Thread t = new Thread(){
  public void run(){
    for(Iterator iter1= a.iterator();iter1.hasNext();){
     System.out.println(iter1.next());
    }  
  }
 };

 Thread t2 = new Thread(){
  public void run(){
   for(int i=0;i<1000;i++){
    a.add(1);
   }
   
  }
 };

 Thread t3 = new Thread(){
  public void run(){
 
    a.removeAll(b);
 
   
  }
 };

 public static void main(String[] args)throws Exception{
  ThreadIterTest thread_iter = new ThreadIterTest();
  //thread_iter.t.start();
  thread_iter.t2.start();
  thread_iter.t3.start();
//  while(true){
//   //toString(),removeAll中用到了Iter
//    System.out.println(thread_iter.a);
//    if(thread_iter.a.size()!=0){
//    // b.addAll(thread_iter.a);
//     //Thread.sleep(300);
//     
//    // b.removeAll(thread_iter.a);
    System.out.println(b);
//    }
//    if(thread_iter.a.size()>50) break;
//    
//  }
    
 }
}

        t,t2,t3线程都有相互冲突的可能; 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值