使用lambda的parallelStream().forEach处理大的数据的时候,发现会有数据丢失或者下标越界问题

在处理大数据集时,使用lambda的parallelStream().forEach可能导致数据丢失或下标越界。问题源于ArrayList的非线程安全add方法。解决方案包括:改用stream或foreach,使用线程安全的CopyOnWriteArrayList或Collections.synchronizedList。选择并行处理需考虑任务独立性、结果顺序依赖等因素。
摘要由CSDN通过智能技术生成

今天再处理kafka日志消息时,按批次每次处理10000条,最后发现每批次处理结果都会比实际数量少一些,最后对代码进行跟踪发现问题,记录下。

我们都知道parallelStream使用的时ForkJobTask。而Fork/Join框架是通过把一个大的任务不断的fork成许多子任务,然后多线程执行这些子任务,最后再join这些子任务得到最终结果数据。

也就是说,如果你有一个大的数据集要处理,它会将你的数据集切分成若干个小的集合,处理之后再进行聚合,但是我的数据集是ArrayList类型,他的add方法不是线程安全的,不能保证原子性。

ArrayList的add方法源码如下:

/**
 * Appends the specified element to the end of this list.
 *
 * @param e element to be appended to this list
 * @return <tt>true</tt> (as specified by {@link Collection#add})
 */
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

可以看到add方法可以概括为以下两个步骤

  1. ensureCapacityInternal(),确认下当前ArrayList中的数组,是否还可以加入新的元素。如果不行,就会再申请一个:int newCapacity = oldCapacity + (old
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值