java.util.ConcurrentModificationException at java.util.ArrayList$ArrayListIterator.next(ArrayList.

java.util.ConcurrentModificationException at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)的解决

在项目里面 遇到了这个bug :

java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
at com.wanyue.tool.CleanActivity.clean(CleanActivity.java:149)

查看了下 这个异常介绍:

An ConcurrentModificationException is thrown when a Collection is modified and an existing iterator on the Collection is used to modify the Collection as well.  

ConcurrentModificationException 抛出的条件 大意是: 一个迭代器在迭代集合的时候 集合被修改了

举个通俗的栗子
例如 在迭代 Arraylist 的时候 对Arraylist进行增删操作 就会抛出该异常

分析原因:
集合中 list set 等 都没有实现同步 , 在多线程中 对集合进行操作时 同步操作都是由外部进行控制

再来看一下 Iterator 的工作原理

An iterator over a sequence of objects, such as a collection.

If a collection has been changed since the iterator was created, methods next and hasNext() may throw a ConcurrentModificationException. It is not possible to guarantee that this mechanism works in all cases of unsynchronized concurrent modification. It should only be used for debugging purposes. Iterators with this behavior are called fail-fast iterators.

Implementing Iterable and returning an Iterator allows your class to be used as a collection with the enhanced for loop.

翻译是
如果集合已经改变自创建迭代器,next和hasNext方法()可能抛出ConcurrentModificationException。这是不可能的,以保证这一机制的工作中不同步并发修改的所有情况。它应该只用于调试的目的。迭代器与这种行为被称为快速失败的迭代器。

按照Iterator的工作原理 应该是在一个独立线程里面完成 且Iterator 执行的时候 迭代的对象必须是不可变的 单向的 顺序的

来看看实际解决方案:

1) 在需要迭代的时候 增加一个 锁
但是比较影响效率

2) 每次前迭代 将集合复制一遍

Arraylist 里面有个toarray()方法

    /**
     * Returns a new array containing all elements contained in this
     * {@code ArrayList}.
     *
     * @return an array of the elements from this {@code ArrayList}
     */
    @Override public Object[] toArray() {
        int s = size;
        Object[] result = new Object[s];
        System.arraycopy(array, 0, result, 0, s);
        return result;
    }

toArray() 方法 会调用 System.arraycopy(array, 0, result, 0, s); 将集合copy一遍

在多线程 当我需要迭代Arraylist的时候 在集合后面增加一个 toArray() 将集合复制一遍 .
这样对原集合进行的修改操作并不会影响到copy后的新集合

在迭代时对原集合调用一下xx.toArray();方法即可。
特此记录一下。欢迎交流。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值