Java8流出奇怪的行为

Jea*_*ung 5 java performance java-8 java-stream

我正在测试一些Java8流API代码,但我无法弄清楚这个代码发生了什么.

我在考虑ParallelStream以及它是如何工作的,我进行了一些比较.两个不同的方法进行大迭代,添加32.768.000个BigDecimals,一个使用ParallelStream,另一个使用正常迭代.我参加了一项测试,我知道它无效,但有些事情引起了我的注意.

测试是:

并行流:

private static void sumWithParallelStream() {
    BigDecimal[] list = new BigDecimal[32_768_000];
    BigDecimal total = BigDecimal.ZERO;
    for (int i = 0; i < 32_768_000; i++) {
        list[i] = new BigDecimal(i);
    }
    total = Arrays.asList(list).parallelStream().reduce(BigDecimal.ZERO, BigDecimal::add);
    System.out.println("Total: " + total);
}
Run Code Online (Sandbox Code Playgroud)

普通代码:

private static void sequenceSum() {
    BigDecimal total = BigDecimal.ZERO;
    for (int i = 0; i < 32_768_000; i++) {
        total = total.add(new BigDecimal(i));
    }
    System.out.println("Total: " + total);
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Total: 536870895616000
sumWithParallelStream(): 30502 ms

Total: 536870895616000
sequenceSum(): 271 ms
Run Code Online (Sandbox Code Playgroud)

然后我尝试删除parallelStream:

 private static void sumWithParallelStream() {
    BigDecimal[] list = new BigDecimal[32_768_000];
    BigDecimal total = BigDecimal.ZERO;
    for (int i = 0; i < 32_768_000; i++) {
        list[i] = new BigDecimal(i);
        total = total.add(list[i]);
    }
    System.out.println("Total: " + total);
}
Run Code Online (Sandbox Code Playgroud)

看到sequenceSum()方法是相同的

新输出:

Total: 536870895616000
sumWithParallelStream(): 13487 ms

Total: 536870895616000
sequenceSum(): 879 ms
Run Code Online (Sandbox Code Playgroud)

我做了这些更改,parallelStream多次添加和删​​除方法,结果sequenceSum()永不改变,总是200在使用parallelStream其他方法时,以及800何时不使用.在Windows和Ubuntu中进行测试.

最后,还有两个问题,为什么parallelStream第一种方法的使用会影响第二种方法?为什么在数组上存储BigDecimals使第一个方法太慢(800 msto 13000 ms)?

Jea*_*ung 0

正如 @apangin 的评论所指出的,问题出在垃圾收集器上。

我添加了-XX:+PrintGCDetails命令行参数,可以打印每次 GC 运行的执行时间。然后我可以确认,使用parallelStreamGC 时需要更多时间来运行,可能是因为 Streams API 初始化和预热消耗了更多内存并留下了一些垃圾需要收集。