记一次特殊的ConcurrentModificationException异常

    关于List的ConcurrentModificationException异常,想必大家都遇到过。一般都是在遍历集合时,对其进行了删除操作。大家都知道使用for循环替代foreach即可避免此问题。

    今天遇到了另一种情况的ConcurrentModificationException异常,在此记录下。

    看下下面的代码:

   

List<Info> Lists = ConfigAPI.getList();
Log.d(TAG, "lists:" + Lists);

    就是这短短的两句话,就抛出了ConcurrentModificationException异常。大家看到这里想必和我一样疑惑,这怎么会有问题??我又修改。其实分析一下源码来看看。

    报的异常信息可以方便我们快速定位,异常信息如下:

    

at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
at java.util.AbstractCollection.toString(AbstractCollection.java:372)
at java.lang.StringBuilder.append(StringBuilder.java:202)

    通过日志我们知道,打印时会调用集合的toString方法,把集合转成字符串,在AbstractorCollection的toString方法中,我们看到了熟悉的代码,如下:

    

public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

    在toString方法中,调用了迭代器的next方法。然后modCount不等于expectedModCount,抛出异常。

    然后再结合代码分析,在多线程的情况下,线程A在执行完获取集合并开始打印时,通过上面分析我们知道,打印时会遍历集合。线程B又开始执行获取集合的操作,由于引用是同一个,线程A和线程B拿到的是同一个list的引用,当线程A对集合进行遍历时,线程B对集合进行了修改。此时触发线程A抛异常。

   分析了这些,解决方案也就有了。就是每次都new一个集合,这样多线程下也不是同一个引用了。

   方案如下:

   

​
List<Info> Lists = new ArrayList();
lists.addAll(ConfigAPI.getList());


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值