Java SE8中parallelStream的优点

时间:2014-05-30 10:21:50

标签: java lambda java-8 java-stream

我只是阅读一些Java 8代码,根据我的理解,您可以使用Stream()或parallelStream()迭代集合。后者的优点是使用并发性将任务分配到现代多核处理器上并加快迭代速度(虽然它不能保证结果的顺序)。

Oracle Java tutorial的示例代码:

double average = roster
        .stream()  /** non-parallel **/
        .filter(p -> p.getGender() == Person.Sex.MALE)
        .mapToInt(Person::getAge)
        .average()
        .getAsDouble();    

double average = roster
        .parallelStream()
        .filter(p -> p.getGender() == Person.Sex.MALE)
        .mapToInt(Person::getAge)
        .average()
        .getAsDouble();

如果我有一个集合并且我不关心它的处理顺序(即它们都有唯一的ID或无论如何都是无序的或处于预先排序的状态),那么总是使用parallelStream方式是否有意义迭代一个集合?

除了我的代码在单个核心机器上运行时(此时我假设JVM会将所有工作分配给单个核心,因此不会破坏我的程序), 到处使用parallelStream()有什么缺点吗?

1 个答案:

答案 0 :(得分:0)

如果您倾听来自Oracle的人们谈论Java 8背后的设计选择,您会经常听到并行性是主要动机。并行化是lambdas,流API和其他方面的主要驱动力。 我们来看一下流API的一个例子。

private long countPrimes(int max) {
         return range(1, max).parallel().filter(this::isPrime).count();
}

private boolean isPrime(long n) {
            return n > 1 && rangeClosed(2, (long) sqrt(n)).noneMatch(divisor -> n % divisor == 0);
} 

这里我们有方法countPrimes,它计算1到最大值之间的素数数。数字流由范围方法创建。然后将流切换到并行模式,过滤掉非素数的数字,并计算剩余的数字。

您可以看到流API允许我们以简洁紧凑的方式描述问题。而且,并行化只是调用parallel()方法的问题。当我们这样做时,流被分成多个块,每个块独立处理,结果总结在最后。由于我们的isPrime方法的实现极其无效且占用大量CPU,因此我们可以利用并行化并利用所有可用的CPU内核。 引用: http://java.dzone.com/articles/think-twice-using-java-8