Java8 如何正确高效的使用并行流
什么是并行流
在 Java8 中,我们可以使用 Stream API 提供的 parallel() 方法来创建并行流,将一个大任务划分成多个小任务并行执行。
如何使用并行流
小心使用
并行流虽然可以大大提高执行效率,但是在使用时需要小心,因为它并不是万能的,有时候反而会降低效率。以下是一些使用并行流时需要注意的点:
- 并行流不一定更快:不要觉得用了并行流就一定比串行流快,它并不是适用于所有场景的。在数据处理量不够大以及流的初始数据结构不适合分成多个部分计算时,并行流的效果不如串行流。
- 并行流会导致更多的上下文切换:并行流必须通过线程池来执行,而线程的创建、切换、销毁都需要额外的时间。因此,当数据处理速度不够快或者线程池的容量不够大时,会出现更多的上下文切换,导致效率降低。
- 并行流可能无序:当数据源是集合时,使用并行流会导致数据的处理结果无序输出。这是因为并行流对于集合内部的数据处理顺序是不保证的。
示例一:计算 1 到 100 的和
首先使用串行流:
long sum = Stream.iterate(1L, i -> i + 1)
.limit(100)
.reduce(0L, Long::sum);
再使用并行流:
long sum = Stream.iterate(1L, i -> i + 1)
.limit(100)
.parallel()
.reduce(0L, Long::sum);
可以通过运行时间比较来看并行流的效果:
long start = System.currentTimeMillis();
long sum = Stream.iterate(1L, i -> i + 1)
.limit(1000000000L)
.reduce(0L, Long::sum);
System.out.println("result: " + sum + ", time: " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
sum = Stream.iterate(1L, i -> i + 1)
.limit(1000000000L)
.parallel()
.reduce(0L, Long::sum);
System.out.println("result: " + sum + ", time: " + (System.currentTimeMillis() - start));
输出结果:
result: 500000000500000000, time: 3587
result: 500000000500000000, time: 2080
可以看到,使用并行流比串行流快了不少。
示例二:将字符串转为大写并排序
使用串行流:
List<String> strings = Arrays.asList("a", "c", "b", "d");
List<String> upperStrings = strings.stream()
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
再使用并行流:
List<String> strings = Arrays.asList("a", "c", "b", "d");
List<String> upperStrings = strings.parallelStream()
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
由于只有四个元素,所以并行流比串行流慢了不少。
总结
并行流可以大大提高程序的执行效率,但是一定要小心使用,避免出现效率反而降低的情况。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java8 如何正确高效的使用并行流 - Python技术站