ArrayList 使用迭代抛出ConcurrentModificationException解决方法
来源:互联网 发布:js路由重置 编辑:程序博客网 时间:2024/05/28 05:18
注意,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( ) { @Override public 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解决方法
- ArrayList 使用迭代抛出ConcurrentModificationException解决方法
- ArrayList迭代,删除list中内容出现ConcurrentModificationException
- java使用Iterator迭代出现"java.uitl.ConcurrentModificationException"错误原因及解决方法概述
- Collection 或 Map 进行迭代操作抛出 java.util.ConcurrentModificationException 异常
- ArrayList引起的ConcurrentModificationException 异常原因及解决方法
- synchronizedList与会抛出ConcurrentModificationException
- 抛出错误ConcurrentModificationException。
- 迭代Iterator结合ArrayList集合的使用及基本使用,再看迭代Iterator原理
- ConcurrentModificationException解决方法
- 使用CopyOnWriteArrayList来解决ArrayList上的ConcurrentModificationException
- 使用CopyOnWriteArrayList来解决ArrayList上的ConcurrentModificationException
- 使用CopyOnWriteArrayList来解决ArrayList上的ConcurrentModificationException
- 解决 ArrayList 的 ConcurrentModificationException
- 解决ArrayList的ConcurrentModificationException
- Java ArrayList异常-ConcurrentModificationException
- 说说ArrayList的ConcurrentModificationException
- Iterator 迭代 警惕 java.util.ConcurrentModificationException异常
- POJ 2155 Matrix (二维树状数组)
- 最小树形图
- 自定义NavigationBar的返回按钮和标题
- 海量数据相似度计算之simhash和海明距离
- 全局最小割
- ArrayList 使用迭代抛出ConcurrentModificationException解决方法
- 几种经典的网络服务器架构模型的分析与比较
- 次小生成树
- 日志20121217~1228
- c++实现获取图片文件格式
- SPFA
- 想爬得更高,需要知道的数学体系
- 很久没写博客了~
- SharePoint 2010 最佳实践学习总结------第2章 SharePoint Windows PowerShell指南