并发修改异常(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语句使其相等,所以使用迭代器不会报错

并发修改异常(ConcurrentModificationException)的更多相关文章

  1. 理解和解决Java并发修改异常ConcurrentModificationException(转载)

    原文地址:https://www.jianshu.com/p/f3f6b12330c1 理解和解决Java并发修改异常ConcurrentModificationException 不知读者在Java ...

  2. 集合框架之——迭代器并发修改异常ConcurrentModificationException

    问题: 我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现. 使用普通迭代器出现的异常: ...

  3. 大杂烩 -- Iterator 并发修改异常ConcurrentModificationException

    基础大杂烩 -- 目录 大杂烩 -- Java中Iterator的fast-fail分析 大杂烩 -- Iterator 和 Iterable 区别和联系 问题: 在集合中,判断里面有没有" ...

  4. 理解和解决Java并发修改异常:ConcurrentModificationException

    參考文獻:https://www.jianshu.com/p/f3f6b12330c1 文獻来源:简书 关键字: Java Exception遇到异常信息Exception in thread &qu ...

  5. 并发修改异常ConcurrentModificationException

    1.简述:在使用 迭代器对象遍历集合时,使用集合对象修改集合中的元素导致出现异常 public static void main(String[] args) { List<Integer> ...

  6. ConcurrentModificationException(并发修改异常)的解决

    [异常解释] ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常.[产生的原因] 迭代器是依赖于集合而存在的,在判断成功后,集合 ...

  7. ConcurrentModificationException 集合并发修改异常 解决

    import java.util.ArrayList; import java.util.List; import java.util.ListIterator; /** * 问题? * 有一个集合, ...

  8. java 15 - 8 集合框架(并发修改异常的产生原因以及解决方案)

    问题?   我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现.  面试题: Concu ...

  9. Java基础知识强化之集合框架笔记19:List集合迭代器使用之 并发修改异常的产生原因 以及 解决方案

    1. 我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现. ConcurrentModi ...

随机推荐

  1. c#中的gcAllowVeryLargeObjects和OutOfMemoryException

    什么是gcAllowVeryLargeObjects 在.net4.5中新增一个配置项 “gcAllowVeryLargeObjects” ,msdn解释如下: 在64位平台上,可以允许总共大于2千兆 ...

  2. vue.js - 1

    最近开发公司vue前端项目,做一下笔记,偶尔上来查漏补缺 Vue指令之v-bind的三种用法 直接使用指令v-bind 使用简化指令: 在绑定的时候,拼接绑定内容::title="btnTi ...

  3. 网络基础、ftp任务(进度条、计算文件大小、断点续传、搭建框架示例)

    一.网络基础 1.端口,是什么?为什么要有端口? 端口是为了将同一个电脑上的不同程序进行隔离. IP是找电脑:端口是找电脑上的应用程序: 端口范围:1 – 65535 :    1 - 1024 不要 ...

  4. Python MySQL - 进行数据查询

    #coding=utf-8 import mysql.connector import importlib import sys # reload(sys) # sys.setdefaultencod ...

  5. C#6.0语言规范(十九) 文档注释

    C#为程序员提供了一种机制,可以使用包含XML文本的特殊注释语法来记录他们的代码.在源代码文件中,具有特定形式的注释可用于指示工具从这些注释和它们之前的源代码元素生成XML.使用这种语法的注释称为文档 ...

  6. linux防火墙(三)—— iptables语法之匹配条件

    一.iptables规则的匹配条件类型有三类 1.通用匹配:可直接使用,不依赖于其他条件或扩展,包括网络协议.IP地址.网络接口等条件 2.隐含匹配:要求以特定的协议匹配作为前提,包括端口.TCP标记 ...

  7. tomcat设置默认欢迎页、server.xml配置文件中的标签理解

    一:要求:输入网址,不加文件名便可以访问默认页面 (1)项目中只有静态文件 方法:更改tomcat下的conf目录下的web.xml文件,如下图: <welcom-file-list>元素 ...

  8. Web API 2 对于 Content-Length 要求严格

    最近在做一个工具,里面有一个发起http请求的操作,虽然工具不是用.NET写的,但是测试用服务器软件是.NET写的.在这里选择了ASP.NET MVC和Web API 2. 首先预定义Student与 ...

  9. Python:使用异常处理来判断运行的平台

    try: import termios, TERMIOS 1 except ImportError: try: import msvcrt 2 except ImportError: try: fro ...

  10. c++中堆、栈、自由存储区和常量存储区(转)

    代码段 --text(code segment/text segment)text段在内存中被映射为只读,但.data和.bss是可写的.text段是程序代码段,在AT91库中是表示程序段的大小,它是 ...