java 8流和并行流之间的区别

Posted

技术标签:

【中文标题】java 8流和并行流之间的区别【英文标题】:Difference between java 8 streams and parallel streams 【发布时间】:2015-10-24 11:47:42 【问题描述】:

我使用 Java 8 流和并行流编写代码,以实现相同的功能,并使用自定义收集器执行聚合功能。 当我使用htop 查看 CPU 使用率时,它显示所有 CPU 内核都用于“流”和“并行流”版本。因此,似乎在使用 list.stream() 时,它也使用了所有 CPU。在这里,parallelStream()stream()多核使用方面的确切区别是什么。

【问题讨论】:

非并行流只使用一个线程来处理它们的管道。这是一个艰难的事实。除非您使用流处理进行一些显式的多线程处理,否则任何给定的终端操作都将一次在单个内核上执行。如果您提到 htop 显示所有内核的一些利用率这一事实,那可能只是由于同一线程从内核迁移到内核(未固定到单个内核)。 最好能提供您的程序代码,以便我们重现您的效果。正如 Marko 所说,list.stream() 在发出终端操作的同一线程中按顺序工作,这是 100% 的事实。但是我们无法解释为什么您观察到所有 CPU 利用率,因为我们没有看到您的代码。 请在此处找到代码 - github.com/yogirjoshi/monitortools/blob/master/src/main/java/… 我觉得这个答案可能对你有帮助:***.com/questions/23170832/… 【参考方案1】:

添加到@Hoopje 的答案:

在使用parallelStream ()之前,请阅读:

    它是多线程的。仅仅编写 parallelStream() 来获得并行性在 java 中几乎总是坏主意。在某些情况下它会起作用,但并非总是如此。还有其他方法可以实现并行性,而且几乎总是,在采用多线程解决方案之前您需要深思熟虑。 它使用默认的 JVM 线程池。所以,如果你在做任何阻塞操作,比如网络调用,整个java应用程序都会卡住。那是那里最大的问题。还有其他的任务分配。带有 n 线程的简单 ExecutionService 提供比并行流更好的性能。

您还可以阅读: Java Parallel Streams Are Bad for Your Health! | JRebel by Perforce

【讨论】:

【参考方案2】:

考虑以下程序:

import java.util.ArrayList;
import java.util.List;

public class Foo 
    public static void main(String... args) 
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) 
            list.add(i);
        
        list.stream().forEach(System.out::println);
    

您会注意到,该程序将按照它们在列表中的顺序依次输出从 0 到 999 的数字。如果我们将stream() 更改为parallelStream(),则不再是这种情况(至少在我的计算机上):所有数字都已写入,但顺序不同。所以,显然,parallelStream() 确实使用了多个线程。

htop 的解释是,即使是单线程应用程序也被大多数现代操作系统划分为多个内核(同一线程的一部分可能在多个内核上运行,但当然不能同时运行)。所以如果你看到一个进程使用了​​多个内核,这并不一定意味着程序使用了多个线程。

此外,使用多个线程时性能可能不会提高。同步的成本可能会抵消使用多个线程的收益。对于简单的测试场景,通常是这种情况。例如,在上面的示例中,System.out 是同步的。因此,尽管使用了多个线程,但实际上只能同时写入数字。

【讨论】:

以上是关于java 8流和并行流之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

Java字符流和字节流对文件操作的区别

Firestore 查询流和获取之间的区别?

RecursiveTask和RecursiveAction的使用 以及java 8 并行流和顺序流(转)

内存流和文件流的区别

Java面试题|节点流和处理流区别

Java面试题|输入流和输出流的区别