戴尔|Java:Java 中的顺序流与并行流是什么?

戴尔|Java:Java 中的顺序流与并行流是什么?

Java 中的流是表示为数据管道的对象序列 。 它通常具有数据所在的源和传输的目的地 。 请注意 , 流不是存储库;相反 , 它对数据源(例如数组或集合)进行操作 。 段落中的中间位实际上称为流 。

【戴尔|Java:Java 中的顺序流与并行流是什么?】在传输过程中 , 流通常会经历一种或多种可能的转换 , 例如过滤或排序 , 也可以是对数据进行操作的任何其他过程 。 这通常根据程序员的需要将原始数据定制为不同的形式 。 因此 , 根据对其应用的操作创建一个新流 。 例如 , 当对流进行排序时 , 它会产生一个新流 , 该流会产生一个结果 , 然后再对其进行排序 。 这意味着新数据是原始数据的转换副本 , 而不是原始形式 。
顺序流
除非明确指定为并行 , 否则 Java 中的任何流操作都是按顺序处理的 。 它们基本上是使用单个线程处理其管道的非并行流 。 即使底层系统可能支持并行执行 , 顺序流也永远不会利用多核系统 。 例如 , 当我们应用多线程处理流时会发生什么?即便如此 , 它一次只能在一个内核上运行 。 但是 , 除非明确固定到特定的核心 , 否则它可能会从一个核心跳到另一个核心 。 例如 , 四个不同线程与四个不同内核的处理显然是不同的 , 前者与后者不匹配 。 在单核环境中执行多个线程是完全可能的 , 但并行处理完全是一种不同的类型 。 除了在支持它的环境中执行之外 , 还需要为并行编程设计一个程序 。 这就是并行编程是一个复杂领域的原因 。

并行流
使用并行流的主要动机是使流处理成为并行编程的一部分 , 即使整个程序可能没有并行化 。 并行流利用多核处理器 , 从而显着提高性能 。 与任何并行编程不同 , 它们复杂且容易出错 。 但是 , Java 流库提供了以可靠的方式轻松完成此操作的能力 。 整个程序可能不会并行化 。 但至少处理流的部分可以并行化 。 从某种意义上说 , 它们实际上非常简单 , 我们可以调用一些方法 , 其余的都可以处理 。 有几种方法可以做到这一点 。 一种这样的方法是通过调用 Collection 定义的 parallelStream() 方法来获取并行流 。 另一种方法是在顺序流上调用 BaseStream 定义的 parallel() 方法 。 顺序流由调用并行化 。 请注意 , 底层平台必须支持并行编程 , 例如多核系统 。 否则 , 调用没有意义 。 在这种情况下 , 流将按顺序处理 , 即使我们已经进行了调用 。 如果调用是在已经并行的流上进行的 , 它什么也不做 , 只是简单地返回流 。
为了保证对流应用并行处理的结果与通过顺序处理得到的结果相同 , 并行流必须是无状态的、无干扰的和关联的 。
结论
流 API 长期以来一直是 Java 的一部分 , 但是添加并行处理的调整非常受欢迎 , 同时也是一个非常有趣的特性 。 尤其如此 , 因为现代机器是多核的 , 并且并行编程设计很复杂是一个耻辱 。 Java 提供的 API 提供了在具有顺序执行的整体设计的 Java 程序中加入一些并行编程调整的能力 。 这可能是此功能的最佳部分 。