先决条件: Java的流
Java中的流是对数据源(例如数组或集合)进行操作并支持各种方法的对象序列。它是在Java 8 的Java.util.stream 包中引入的。 Stream支持filter、map、limit、reduce、find、match等多种聚合操作,可以根据程序员的需要将原始数据定制成不同的形式。对流执行的操作不会修改其源,因此会根据对其应用的操作创建一个新流。新数据是原始表单的转换副本。
顺序流
顺序流是使用单个线程来处理流水线的非并行流。任何未明确指定为并行的流操作都被视为顺序流。顺序流的对象在同一处理系统上的单个流中流水线化,因此即使底层系统支持并行执行,它也永远不会利用多核系统的优势。顺序流一一执行操作。
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的一部分,因为它具有有趣的特性。它也因并行处理能力和改进的性能而非常受欢迎。在这个时代,每台现代机器都是多核的,因此对于这个核心,我们应该有效地使用并行流,但是并行编程设计很复杂。因此,完全取决于程序员是否要根据需求使用并行流或顺序流。