Java8 parallelStream使用注意!

举报
xiewenci 发表于 2022/09/16 11:40:39 2022/09/16
【摘要】 使用Java8 parallelStream并行流,抛出数组越界异常

parallelStream是线程不安全的,使用以下代码时
image.png

集合里面可能会存在null元素或者抛出下标越界的异常信息
原因:ArrayList不是线程安全的集合,add方法在多线程环境下会存在并发问题
存在null元素原因:
image.png

数组越界的原因:
先看list的add源码

public boolean add(E e) {
 ensureCapacityInternal(size + 1); 
 elementData[size++] = e; 
return true; }

假设当前数组刚好只能添加一个元素,两个线程同时进入: ensureCapacityInternal(size + 1),同时读取的size值,加1后进入ensureCapacityInternal都不会导致扩容,退出ensureCapacityInternal后,两个线程同时elementData[size] = e,线程B的size++先完成,假设此刻线程A读取到了线程 B的更新,线程A再执行size++,此时size的实际值就会大于数组的容量,这样就会发生数组越界异常。
解决办法:

  • 不使用parallelStream,因为parallelStream是并行流,仅在CPU密集型下可以提高运行效率,在循环中计算量不是特别大的时候,直接使用原始集合遍历或者stream()

  • 在parallelStream中的操作使用线程安全的集合,如

    Collections.synchronizedList(new ArrayList());

这种处理只能保证集合中的数据不会存在null值和集合中不会丢失数据,但是不保序

注意:使用ForkJoinPoll,提交任务也不能保证集合中不存在null值
image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。