Java8并行流ParallelStream和Stream的区别就是支持并行执行,提高程序运行效率。但是如果使用不当可能会发生线程安全的问题。Demo如下:
程序运行结果如下:
除了以上在ForEach里面添加集合元素会出现这种问题,以下这种方式也会:
两个问题:
1.为什么parallelStorage的大小不固定?
2.为什么parallelStorage会有null元素?
最初我以为是因为主线程执行完成后并行流中的线程并未结束,sleep了主线程后发现结果并没有发生改变,其实我们可以认为ArrayList内部维护了一个数组Arr其定义一个变量 n用以表式这个数组的大小那么向这个ArrayList中存储数据的过程可以分解为这么几步:
1.读取数组的长度存入n
2.向这个数组中储入元素arr[n]=a
3.将n+1
4.保存n
而对于parrallelStorage元素数量不固定的原因就是多线程有可能同时读取到相同的下标n同时赋值,这样就会出现元素缺失的问题了
如何解决这个问题呢?我们可以将其转化为一个同步集合也就是
在使用并行流的时候是无法保证元素的顺序的,也就是即使你用了同步集合也只能保证元素都正确但无法保证其中的顺序。
除了以上这种方式,还有什么方法可以防止并行流出现线程不安全操作?
那就是最后调用collect(Collectors.tolist()),这种收集起来所有元素到新集合是线程安全的。Demo如下:
程序运行结果如下:
不光没有出现Null和数量不一致问题,还排序了!所以,在采用并行流收集元素到集合中时,最好调用collect方法,一定不要采用Foreach方法或者map方法。
本文同步分享在 博客“寇寇寇先森”(JianShu)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。