ConcurrentModificationException异常
ConcurrentModificationException异常
也叫作并发修改异常
如下:
ArrayList<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
System.out.println(list);
//遍历
//ConcurrentModificationException 并发(同时 两个以上同时)修改异常
//操作元素时保证只有一个对象在操作
Iterator<String> it = list.iterator();
while (it.hasNext()){
String i = (String) it.next();
System.out.println(i);
if (i.equals("222")){
list.remove("222"); //倒数第二个 源码 校验机制(size() -1 ! = 0)=> 执行校验机制
// it.remove(); //不会出现异常
}
}
System.out.println(list);
当运行上述代码时,程序抛出了ConcurrentModificationException异常。
ConcurrentModificationException异常与modCount这个变量有关
modCount的作用。
modCount就是修改次数,在具体的实现类中的Iterator中才会使用。在List集合中,ArrayList是List接口的实现类。
modCount:表示list集合结构上被修改的次数。(在ArrayList所有涉及结构变化的方法中,都增加了modCount的值)
list结构上被修改指的是:改变了list的长度的大小或者是遍历结果中产生了不正确的结果的方式。add()和remove()方法会是的modCount进行+1操作。modCount被修改后会产生ConcurrentModificationException异常, 这是jdk的快速失败原则。
modCount被定义在ArrayList的父类AbstractList中,初值为0,protected transient int modCount = 0。
在进行add()方法是,先调用的ensureCapacity()这个方法,来判断是否需要扩容
在判断是否需要扩容时,用调用ensureExplicitCapacity这个方法,注意,这个方法中对modCount进行的加一操作。所以集合在进行添加元素是会对modCount进行+1的操作。
在进行文章开头的代码时list集合中使用add添加了元素后,size=3,modCount=3。
Iterator的方法是返回了一个Itr()的类的一个实例。
在for循环内部首先对Iterator进行了初始化,初始化。expectedModCount=3,cursor=0。
hasNext是判断是否有下一个元素,判断条件是cursor不等于size,有下一个元素。size=3,cursor=0,是有下一个元素的。
当进行next()方法时,调用了checkForComodification()方法,进行判断是否抛出异常
可以看见进行remove操作时,是通过调用fastRemove()方法进行的实际删除。在fastRemove()方法中,对modCount进行了+1的操作。
此时,modCount=expectedModCount=3,不抛异常,程序继续进行,next()方法有对cursor进行了加一的操作。cursor=1。e=“222”。此时进行remove删除操作。
ArrayList中remove实际在调用fastRemove()方法进行实际的删除,modCount进行了+1操作,modCount=4,size进行了-1的操作,size=2,程序继续进行,cursor=1,size=2,进行next()方法,发现modCount不等于expectedModCount,抛出了ConcurrentModificationException异常。
解决方法:
使用Iterator提供的remove方法,用于删除当前元素。
建立一个集合,记录需要删除的元素,之后统一删除。
不使用Iterator进行遍历,需要注意的是得保证索引正常
使用并发集合类来避免ConcurrentModificationException,比如使用CopyOnArrayList,而不是ArrayList
下一篇: shell 提取文件名和目录名
推荐阅读
-
荐 JDK11,8引入不同版本的jjwt异常问题
-
火牛视频显示设备异常无法登录怎么解决?
-
详解Ruby中的异常
-
Java 实例 - 多个异常处理(多个catch)
-
php-PHP调用.NET写的web service时异常,这一般是什么问题。异常错误信息如下
-
.net及其他架构中异常 (Except) 设计准则的详细介绍
-
Django models的诡异异常RelatedObjectDoesNotExist
-
OkHttp3 添加Authorization 异常 Unexpected char 0x0a at 42 in Authorization value 解决
-
php 链接数据库异常
-
php中try catch捕获异常实例详解,trycatch