📜  Java的并行与顺序流

📅  最后修改于: 2021-09-15 01:24:45             🧑  作者: Mango

先决条件: Java的流

Java中的流是对数据源(例如数组或集合)进行操作并支持各种方法的对象序列。它是在Java 8 的Java.util.stream 包中引入的。 Stream支持filter、map、limit、reduce、find、match等多种聚合操作,可以根据程序员的需要将原始数据定制成不同的形式。对流执行的操作不会修改其源,因此会根据对其应用的操作创建一个新流。新数据是原始表单的转换副本。

Java 中的并行与顺序流

顺序流

顺序流是使用单个线程来处理流水线的非并行流。任何未明确指定为并行的流操作都被视为顺序流。顺序流的对象在同一处理系统上的单个流中流水线化,因此即使底层系统支持并行执行,它也永远不会利用多核系统的优势。顺序流一一执行操作。

stream()方法返回Java的顺序流。

例子:

Java
// Java program to understand execution
// of sequential streams
  
import java.io.*;
import java.util.*;
import java.util.stream.*;
  
class SequentialStreamDemo {
    
    public static void main(String[] args)
    {
        // create a list
        List list = Arrays.asList( "Hello ", 
                          "G", "E", "E", "K", "S!");
  
        // we are using stream() method
          // for sequential stream
        // Iterate and print each element
          // of the stream
        list.stream().forEach(System.out::print);
    }
}


Java
// Java code to demonstrate
// ParallelStreams
  
import java.io.*;
import java.util.*;
import java.util.stream.*;
  
class ParallelStreamExample {
    public static void main(String[] args)
    {
        // create a list
        List list = Arrays.asList("Hello ", 
                         "G", "E", "E", "K", "S!");
  
        // using parallelStream() 
        // method for parallel stream
        list.parallelStream().forEach(System.out::print);
    }
}


Java
// Java code to demonstrate Iterating in 
// the same order via parallelStream
  
import java.io.*;
import java.util.*;
import java.util.stream.*;
  
class ParallelStreamWithOrderedIteration {
    
    public static void main(String[] args)
    {
          // create a list
        List list
            = Arrays.asList("Hello ","G", "E", "E", "K", "S!");
        
        // using parallelStream() method for parallel stream
        list.parallelStream().forEachOrdered(System.out::print);
    }
}


输出
Hello GEEKS!

在这个例子中, list.stream()在单个线程上按顺序使用 print() 操作,并且在前面程序的输出中,列表的内容以有序的顺序打印,因为这是一个顺序流。

并行流

使用并行处理是Java 的一个非常有用的特性,即使整个程序可能没有并行化。并行流利用多核处理器,从而提高其性能。使用并行流,我们的代码被分成多个流,这些流可以在系统的不同核心上并行执行,最终结果显示为所有单个核心结果的组合。始终没有必要将整个程序并行化,但至少应该并行化处理流的某些部分。执行顺序不受我们的控制,它会给我们带来不可预测的无序结果,并且与任何其他并行编程一样,它们很复杂且容易出错。

Java流库提供了几种方法来做到这一点。容易,并且以可靠的方式。

  • 获取并行流的一种简单方法是调用Collection接口的parallelStream() 方法。
  • 另一种方法是调用 平行() 顺序流上的BaseStream接口的方法。

重要的是要确保并行流的结果与通过顺序流获得的结果相同,因此并行流必须是无状态、无干扰和关联的。

例子:

Java

// Java code to demonstrate
// ParallelStreams
  
import java.io.*;
import java.util.*;
import java.util.stream.*;
  
class ParallelStreamExample {
    public static void main(String[] args)
    {
        // create a list
        List list = Arrays.asList("Hello ", 
                         "G", "E", "E", "K", "S!");
  
        // using parallelStream() 
        // method for parallel stream
        list.parallelStream().forEach(System.out::print);
    }
}
输出
ES!KGEHello

在这里我们可以看到没有维护顺序,因为 list.parallelStream() 在多个线程上并行工作。如果我们多次运行这段代码,那么我们还可以看到,每次我们都得到不同的输出顺序,但是这个并行流提高了性能,所以顺序不重要的情况是最好的使用技术。

注意:如果我们想让并行流中的每个元素都被排序,我们可以使用 forEachOrdered() 方法,而不是 forEach() 方法。

例子:

Java

// Java code to demonstrate Iterating in 
// the same order via parallelStream
  
import java.io.*;
import java.util.*;
import java.util.stream.*;
  
class ParallelStreamWithOrderedIteration {
    
    public static void main(String[] args)
    {
          // create a list
        List list
            = Arrays.asList("Hello ","G", "E", "E", "K", "S!");
        
        // using parallelStream() method for parallel stream
        list.parallelStream().forEachOrdered(System.out::print);
    }
}
输出
Hello GEEKS!

我们总是可以根据我们的要求很容易地在并行和顺序之间切换。如果我们想将并行流改为顺序流,那么我们应该使用BaseStream接口指定的sequential()方法。

顺序流和并行流的区别

Sequential Stream

Parallel Stream

Runs on a single-core of the computer Utilize the multiple cores of the computer. 
Performance is poor The performance is high.
Order is maintained Doesn’t care about the order,
Only a single iteration at a time just like the for-loop.  Operates multiple iterations simultaneously in different available cores.
Each iteration waits for currently running one to finish,  Waits only if no cores are free or available at a given time,
More reliable and less error, Less reliable and error-prone. 
Platform independent, Platform dependent

结论

很长一段时间以来,流 API 一直是Java的一部分,因为它具有有趣的特性。它也因并行处理能力和改进的性能而非常受欢迎。在这个时代,每台现代机器都是多核的,因此对于这个核心,我们应该有效地使用并行流,但是并行编程设计很复杂。因此,完全取决于程序员是否要根据需求使用并行流或顺序流。