ArrayList 使用迭代抛出ConcurrentModificationException解决方法
注意,ArrayList实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,而其中至少一个线程从结构上修改了列表,那么它必须 保持外部同步。(结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用Collections.synchronizedList
方法将该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问:
List list = Collections.synchronizedList(new ArrayList(...));
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的remove 或add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException
。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。
注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
测试
package my.test;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/***@author E-mail: xyylchq@163.com*@version 创建时间:2012-8-15下午02:11:03*类说明*/
public class ConcurrentModificationExceptionTest {public static void main(String[] args) {final ArrayList<Object> list = new ArrayList<Object>();for(int i = 0; i < 5; i ++) {list.add(i);}List<Object> list2 = (List)list.clone();
// list.clear();
// System.out.println(list2.size());Runnable run = new Runnable( ) {@Overridepublic void run() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("3秒过后给list赋值");//添加测试list.add("sd");list.add("sd");//删除测试
// list.clear();}};new Thread(run).start();Iterator<Object> iterator = list.iterator();
// for(int i = 0; i < list.size(); i++) {while(iterator.hasNext()) {System.out.println(iterator.next());
// System.out.println(list.get(i));try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}}}
解决方法:
1. 使用 Collections.synchronizedList
方法将该列表“包装”起来。
2. 将要创建的ArrayList创建一个副本,clone出一个副本。
这里还需要注意的是 Collections.synchronizedList这个方法的使用。
下面是转帖内容:
private List<JobInfo> mJobList;
mJobList = Collections.synchronizedList(new ArrayList<JobInfo>());
这种写法是正确的,因为synchronizedList方法的返回值就是List集合的,但是看看下面这种写法
private ArrayList<JobInfo> mJobList;
mJobList = (ArrayList<JobInfo>)Collections.synchronizedList(new ArrayList<JobInfo>());
这种写法看起来时正确的,实际上会报异常“Caused by: java.lang.ClassCastException: java.util.Collections$SynchronizedRandomAccessList”
分析一下:
1. 函数的<T> List<T>是什么意思?
我知道的是返回一个List类型的集合,它里面存储的对象的类型是T,但是最前面的那个<T>又是什么意思呢?
在这个泛型方法中,类型参数是T,它位于函数的所有的修饰符之后,返回值之前,放在尖括号中,这个T是该函数的类型参数,而List<T>中的T是这个集合的类型参数
List<T>:参数化类型的返回值。
接下来让我们看看synchronizedList方法的源码:
public static <T> List<T> synchronizedList(List<T> list) {
if (list == null) {
throw new NullPointerException();
}
if (list instanceof RandomAccess) {
return new SynchronizedRandomAccessList<T>(list);
}
return new SynchronizedList<T>(list);
}
mJobList = (ArrayList<JobInfo>)Collections.synchronizedList(new ArrayList<JobInfo>());这行代码中,给synchronizedList方法传递了一个ArrayList类型的参数,ArrayList实现了RandomAccess接口,所以
会去执行return new SynchronizedRandomAccessList<T>(list);这行代码,这时我们来看看uml类图,其中SynchronizedRandomAccessList,SynchronizedList,SynchronizedCollection这三个类都是Collections工具类的static内部类
通过这个图我们可以看到,SynchronizedRandomAccessList是List的子类,他不是ArrayList类型的,因此上面代码的强转是不对的,此外我们还可以看出这是一个包装模式,关于包装模式以后再写。
ArrayList 使用迭代抛出ConcurrentModificationException解决方法相关推荐
- foreach去除重复元素java_Java foreach 中List移除元素抛出ConcurrentModificationException原因全解析...
本文重点探讨 foreach 循环中List 移除元素造成 java.util.ConcurrentModificationException 异常的原因. 先看<阿里巴巴 Java开发手册&g ...
- 多线程下ArrayList类线程不安全的解决方法及原理
多线程下ArrayList类线程不安全的解决方法及原理 参考文章: (1)多线程下ArrayList类线程不安全的解决方法及原理 (2)https://www.cnblogs.com/fangting ...
- SVN地址正确,能在网页打开,但是检出失败解决方法
SVN地址正确,能在网页打开,但是检出失败解决方法 参考文章: (1)SVN地址正确,能在网页打开,但是检出失败解决方法 (2)https://www.cnblogs.com/zzd0916/p/76 ...
- Win10电脑键盘失灵打不出字解决方法分享
Win10电脑键盘失灵打不出字解决方法分享.键盘连接到电脑之后,有用户发现自己的键盘打字的时候无法正常使用,出现了按键失灵的情况.但是换到其他电脑时却可以使用.那么这个情况是自己的电脑哪里出现了设置错 ...
- 计算机主机打开光驱,电脑开机光驱自动弹出来怎么办?电脑DVD光驱自动弹出的解决方法...
虽然目前家用电脑中,很多用户装机都不搭配DVD光驱了,但是还是有一些用户会使用到的,就在近期有一网友称自己电脑的DVD光驱会自动弹出,那么遇到电脑开机光驱自动弹出来怎么办?下面装机之家小编分享一下电脑 ...
- 笔记本电脑启动计算机出现了页面,笔记本电脑开机弹出广告解决方法
有很多小伙伴反映在使用笔记本电脑的时候经常会出现很多的小广告,无论是玩游戏的时候,还是看电影的时候,以及在看网页的时候都有,具体该怎么解决呢?下面就由学习啦小编跟大家分享一下解决方法吧,欢迎大家来阅读 ...
- 计算机无法跳转登录页面,电脑连接校园网后CMCC登录界面不能弹出的解决方法...
电脑连接校园网后CMCC登录界面不能弹出怎么办?这是近来不少朋友都向小编反馈的问题.他们表示自己的计算机在连接校园网CMCC后登录界面无法弹出,并且无法通过手动打开网页的事,多次尝试笔者发现这是LSP ...
- ArrayList类线程不安全的解决方法
/*** 描述: ArrayList线程不安全由于add方法没加锁,多线程高并发情况下java.util.ConcurrentModiricationException异常** @author xin ...
- 出现“未报告的异常错误,必须对其进行捕获或声明以便抛出”的解决
错误:未报告的异常错误,必须对其进行捕获或声明以便抛出 出现错误:是因为没有对异常进行捕获或声明 首先说一下Java 中throws的作用: 假如函数部分有不合法的异常,例如分母为0: import ...
最新文章
- Java面试题之Oracle 支持哪三种事务隔离级别
- 7-flutter Navigator 和Route
- html外链式css运行不出来div,html+css外链式
- 关于使用python的open函数时报No Such File or DIr的错误
- nginx-tomcat负载均衡redis-session共享,静态资源分离
- SpringBoot @Cacheable自定义KeyGenerator
- 岗位内推 | 深睿医疗实验室招聘机器学习实习生
- jBPM与业务系统集成-通过定制Task Instance等方式实现
- centos7 go yum 安装_Centos7.6从头开始安装nvidiadocker
- 怎么把框架栏变颜色 html,如何修改easyui框架颜色,求指点_html/css_WEB-ITnose
- 电路串联和并联图解_初三物理串联和并联电路知识大全
- Airprint across subnets(2)
- QT+Opencv配置+问题:During startup program exited with code 0xc0000135.
- IDEA 2019 激活码(注册码)
- 软考易错知识点(自用)
- mysql mongo关联查询语句_MySQL与Mongo简单的查询实例代码 筋斗云网络
- Python 3 迁移怨声载道
- php前台限制输入text字符,限制字符输入数功能(jquery版和原生JS版)
- C#学习(十五)——窗体控件用法大全
- Java中可变类型和不可变类型