Java8 流奇怪的行为

标签 java performance java-8 java-stream

我正在对一些 Java8 Streams API 片段进行基准测试,但我无法弄清楚这个片段发生了什么。

我在想ParallelStream以及它实际上是如何工作的,并试图在顺序处理和并行处理之间进行一些比较。 我创建了两种不同的方法,都在添加 32.768.000 BigDecimal 的同时进行了巨大的迭代s,其中一个使用 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);
}

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);
}

输出是:

Total: 536870895616000
sumWithParallelStream(): 30502 ms

Total: 536870895616000
sequenceSum(): 271 ms

然后我尝试删除 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);
}

关注sequenceSum()方法不变

令人惊讶的是,新的输出是:

Total: 536870895616000
sumWithParallelStream(): 13487 ms

Total: 536870895616000
sequenceSum(): 879 ms

我多次重复这些更改,添加和删除 parallelStream调用,结果为 sequenceSum()是一致的,当 parallelStream 时 ~200ms涉及,~800ms 不涉及。在不同的机器、Windows 和 Ubuntu 中测试。

最后,我的两个问题是:

  1. 为什么使用 parallelStream第一种方法会干扰第二种方法吗?
  2. 为什么要存储 BigDecimal数组中的实例使第一个方法变慢了很多(800 毫秒到 13000 毫秒)?

最佳答案

在第一个示例中,您分配了一个包含 32,768,000 个元素的数组,然后对其进行流处理。不需要数组分配和内存获取,这可能是减慢方法速度的原因。

IntStream.range(0, limit).parallel()
   .mapToObj(BigDecimal::new)
   .reduce(BigDecimal.ZERO, BigDecimal::add);

关于Java8 流奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31025611/

相关文章:

java - Lucene搜索不适用于字符串数字组合java

MYSQL:使用大表进行 INNER JOIN 的替代方案(太慢了)

java - 按第一个字符对单词进行分组

java - Java8 中的 HashMap 条目对流?

java - 套接字编程ConnectException

java - 如何在冒号分隔的字符串中查找最后 2 项的字符串

java - 使用 eclipse、maven、spring、hibernate、jsf 快速重新加载开发中的 java web 应用程序中的更改

java - 如何在 Java 的 Lambda API 中构建复制函数的映射

java - OSGi 中的 AWS SDK 导致 "Unable to resolve/Missing requirement"错误

java - 如何返回 <T extends Comparable< 的通用数组? Java 中的 super T>>?