ConcurrentModificationException错误的一次解决经历

测试环境上有时调用满减接口会抛错,通常是出现在店铺比较多的时候.

看了一下错误日志,提示我们是ConcurrentModificationException错误.这个错误很明显,是ArrayList在迭代的时候同时对其进行了修改时抛出的异常.

看了一下代码.大致如下:

List a = Lists.newArrayList();

b.stream().foreach{

  .......

  if (true){

     a.add(c);

  }

  for(A a: a){

    a.add(c);

  }

}

大致就是这个意思.在stream中对A进行了遍历及add操作.

而我们知道stream流是有可能隐式的开启多线程的.那么原因就很明显了,由于店铺较多,导致虚拟机选择开启多线程,从而导致了此问题.

我们知道ArrayList是线程不安全的,那么我们把这个集合改成线程安全的不就解决了么.

查了一下,发现CopyOnWriteArrayList很符合我们的要求.

简介就不说了,百度一下就知道了.我们看一下他的add方法.

大致说明一下,首先类里面有一个ReentrantLock,用来加锁.

进入add方法后先加个锁,然后获得CopyOnWriteArrayList内层的数组,拷贝一份,把新元素加到新数组后面,然后把CopyOnWriteArrayList内层的数组指向新数组.解锁.

所以我们可以知道,如果线程A运行到把新元素加到新数组后面之类的地方,还没有指向新数组的时候,线程B去读取数据,读取到的仍然是原来的值.

对于我的这个场景来说,重复是可以接受的,所以就这样就OK了,如果重复数据是不能接受的,那么我们可以在stream操作结束后进行一次去重.

 

转载于:https://www.cnblogs.com/tyoutetu/p/11061187.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值