zoukankan      html  css  js  c++  java
  • 一种较为隐蔽ConcurrentModificationException情形

    ConcurrentModificationException是遍历过程中修改list而抛出的错误。就像前面分析的,单线程时这种错误主要是因为使用forEach造成:遍历一个拷贝,修改原始list,造成的。简单的大家都知道,这里要说一种比较隐蔽的出错方式:

     1 public class ExceptionTest{
     2 
     3     private List<String> list = new ArrayList<>();
     4 
     5     public ExceptionTest(){
     6         for(int i=0;i<9;i++){
     7             list.add("string"+i);
     8         }
     9     }
    10     
    11     public void throwExceptions(){
    12         List<List<String>>  listList = new ArrayList<>();
    13         listList.add(list.subList(0,3));
    14         listList.add(list.subList(3,6));
    15         listList.add(list.subList(6,8));
    16         Iterator<List<String>> it1 = listList.iterator();
    17         while(it1.hasNext()){
    18             List<String> l = it1.next();
    19             Iterator<String> it = l.iterator();
    20             while(it.hasNext()){
    21                 String str = it.next();
    22                 if(str.endsWith(("5"))){
    23                     it.remove();
    24                 }
    25             }
    26         }
    27     }
    28  }

    运行上面的代码还是会出错,虽然两层循环都用来Iterator。如果不仔细看很难发现这其中的原因。当你调试你会发现,删除以5结尾的字符串的时候,listList中的第一个子list会报错,而不是正在做修改的第二个子list。所以这个错误的来源不是两个遍历的本事,而是listList的初始化方式,可以看到13到16行,每个子列表使用的是list的subList方法。进一步查看subList代码可以发现。这个方法其实并未新建list而是返回了原理list的一个视图(其实索引):

    SubList(AbstractList<E> parent,
                    int offset, int fromIndex, int toIndex) {
                this.parent = parent;
                this.parentOffset = fromIndex;
                this.offset = offset + fromIndex;
                this.size = toIndex - fromIndex;
                this.modCount = ArrayList.this.modCount;
            }

    所以在修改第二个子list的时候回引起父列表(list)状态发生改变,虽然两层遍历看起来是正常的,但是他们却是在遍历和修改同一个list,因此会抛出ConcurrentModificationException异常。

    总结:有时候的异常并不是因为当前的步骤引起的,原因有可能来自于之前的某一步骤。

  • 相关阅读:
    SignalR 聊天室实例详解(服务器端推送版)
    一种解决图片防盗链的方法
    python3基础-数学运算
    测试开发之路
    页面加载时让其显示笼罩层与加载等待图片
    在SQL SERVER中获取表中的第二条数据
    html+js 的一些小问题
    数据库连接错误问题
    ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。
    正则表达式实例
  • 原文地址:https://www.cnblogs.com/zziawanblog/p/5272255.html
Copyright © 2011-2022 走看看