You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8数组并行流求和耗时远超串行,求问题排查

并行流求和比串行循环慢的原因分析

你的代码中出现并行流耗时远超串行循环的情况,主要有以下几个核心原因:

1. JVM预热顺序导致测试偏差

你先执行并行流求和,此时JVM处于冷启动状态,JIT编译器还未对相关代码进行即时优化;而串行循环执行时,JVM已经完成热身,JIT已经对循环代码做了优化(比如循环展开、边界检查消除等),这直接导致串行测试的耗时被低估,并行的耗时被高估。

2. 并行流调度开销超过计算收益

int类型求和是极轻量化的计算操作,并行流需要将数组拆分成多个子任务,提交到ForkJoinPool线程池,执行完成后还要合并各个子任务的结果。这些任务拆分、线程调度、结果合并的额外开销,远大于多线程并行计算带来的性能提升。只有当每个并行任务的计算复杂度足够高时,并行流的优势才会显现。

3. 缓存局部性被破坏

串行循环是顺序连续遍历数组,CPU的L1/L2缓存可以高效命中连续的内存地址,缓存命中率极高;而并行流会将数组分割成多个不连续的段,不同线程处理不同段,容易导致缓存行失效,大幅降低缓存利用率,反而比串行遍历更慢。


优化后的测试代码

调整测试顺序并加入JVM预热阶段,能更准确地对比两者的性能:

import java.util.Arrays;
import java.util.Random;

public class MultithreadThing {

    public static int findSum(int[] arr) {
        int sum = 0;
        for (int value : arr) {
            sum += value;
        }
        return sum;
    }

    public static void main(String[] args) {
        Random rand = new Random();
        int arr[] = new int[100000000];
        for(int i=0; i < arr.length; i++) {
            arr[i] = rand.nextInt(10) + 1;
        }

        // JVM预热:先执行5次,让JIT完成代码优化
        for (int i = 0; i < 5; i++) {
            Arrays.stream(arr).parallel().sum();
            findSum(arr);
        }

        // 先测试串行
        long startTime = System.nanoTime();
        int singleSum = findSum(arr);
        System.out.printf("Single sum: %d, time: %d ms%n", singleSum, (System.nanoTime() - startTime) / 1_000_000);

        // 再测试并行
        long startTime2 = System.nanoTime();
        int parallelSum = Arrays.stream(arr).parallel().sum();
        System.out.printf("Parallel sum: %d, time: %d ms%n", parallelSum, (System.nanoTime() - startTime2) / 1_000_000);
    }
}

内容的提问来源于stack exchange,提问作者John Hendricks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:15:39