并发修改异常(ConcurrentModificationException)
程序员文章站
2022-07-02 13:39:33
并发修改异常(ConcurrentModificationException) 这个异常,使用集合的时候应该很常见,这个异常产生的原因是因为java中不允许直接修改集合的结构。 先贴上个有趣的例子,给你们看看: 我们使用list的remove方法删除元素,就抛出了这种并发修改异常,如下: 但是,我们 ......
并发修改异常(ConcurrentModificationException)
这个异常,使用集合的时候应该很常见,这个异常产生的原因是因为java中不允许直接修改集合的结构。
先贴上个有趣的例子,给你们看看:
package com.xiongda; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Confirm { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("4"); list.add("3"); list.add("6"); Iterator<String> iterator = list.iterator(); while(iterator.hasNext()){ String integer = iterator.next(); if(integer.equals("2")) { list.remove("2"); } } System.out.println(list.toString()); } }
我们使用list的remove方法删除元素,就抛出了这种并发修改异常,如下:
但是,我们改为判断倒数第二个数,删除任意元素,就不报错了:
package com.xiongda; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Confirm { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("4"); list.add("3"); list.add("6"); Iterator<String> iterator = list.iterator(); while(iterator.hasNext()){ String integer = iterator.next(); if(integer.equals("3")) { list.remove("2"); } } System.out.println(list.toString()); } }
这是为什么?是不是很神奇?
我昨天研究过源码之后发现,为什么使用arraylist的remove方法会抛出这个异常呢,因为arraylist中的add和remove方法都造成了modcount 和 exceptmodcpiunt不等。
而异常中抛出异常的那个方法checkformodification方法就是检查这两个值知否相等。
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
那么为什么,但判断走到了倒数第二个元素,删除就没有抛出异常了呢?
仔细看抛出的异常,是next方法里面调用的checkformodification方法:
public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }
当判断到倒数第二个的时候,remove掉了一个,此时的index和size相等了,就不执行循环了,就不执行next方法了,所以异常就没有抛出来了
public boolean hasNext() { return cursor != size; }
那么为什么使用迭代器的remove方法不会报错,而使用arraylist的remove方法会报错呢?
这是因为list中的remove方法会使modcount++,但是迭代器中remove方法中多了一条modcount = exceptmodcount语句使其相等,所以使用迭代器不会报错
推荐阅读
-
Oracle查看和修改连接数(进程/会话/并发等等)
-
java 集合并发操作出现的异常ConcurrentModificationException
-
python监控网站运行异常并发送邮件的方法
-
C#解决SQlite并发异常问题的方法(使用读写锁)
-
Oracle查看和修改连接数(进程/会话/并发等等)
-
List并发修改异常的产生和解决
-
《C#并发编程经典实例》学习笔记—2.9 处理 async void 方法的异常
-
Java集合中迭代器遍历过程的并发修改异常问题(Debug模式追踪)
-
java 集合并发操作出现的异常ConcurrentModificationException
-
关于java List的remove方法导致的异常java.util.ConcurrentModificationException