parallelStream引发的生产环境BUG

背景

线上有个接口需要查询返回一个列表数据,原来是采用了Stream进行遍历数据过滤的,随着数据的增长,这个接口一次性需要处理的数据越来越多,然后这期需要对其进行优化。

除去一些其它的DB方法优化,也改动到这里了,改成了parallelStream进行处理。没做好并发处理,埋了个雷!

经过优化后,性能提升也还算比较明显有用,极端数据的情况下缩短了近一半开销。

 

效果这么好,我笑了

事故

然后顺利的通过测试,发布上线...结果第二天就出现异常,还是偶发性异常,根据日志本地重现也无法重现,最后查了下具体的报错信息。数组越界ArrayIndexOutOfBoundsException

知道错误信息,定位到错误行,发现只把stream改成了parallelStream而已,没想到引发了bug。

可以看到git记录只改动了这一个地方,就出现了异常,但是逐行看去发现其中有个操作list的操作,这个有点不对劲。

在采用 ​​​​​stream串行流的时候是没有问题的,数据都是一个个往前走的。但是改成parallelStream并行流就有可能出问题了,因为并行流是多个线程之间一起进行的,就有概率抢占到一起操作这个list(retainAll()保留两个list中都存在的),而我们知道list中的ArrayList是线程不安全的,这就会导致A线程和B线程同时操作这个list

 重现

知道了问题所在就好办了,知道前因后果,那重现一下。

 可以看到,我们执行后就有可能出现这个异常错误了。

 问:那如果非要这么操作list,又要使用parallelStream串行流提高效率,应该怎么处理呢?

答:既然知道同一个list可能会被多个线程操作,那我们是不是可以在每个线程上自己创建一个新的list呢?答案是可以的,在操作list前new一个新的list再操作,这样就避免了

可以看到改造list后的执行,可以顺利执行并且不会抛出数组异常了。

 总结

 任何好的工具都是一把双刃剑,好用的同时也得注意别伤到自己了。

parallelStream用好了效率加倍,用不好就加班。

具体parallelStream的介绍可以看看其它大佬的介绍和详细文档,还有不少坑需要注意。

以后改动的时候还是要多看看其中的业务代码和操作,避免搭配使用又出现BUG。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值