串行流与并行流
//创建一个1~10的list
List<Integer> collect = Stream.iterate(1, x -> x + 1).limit(10).collect(Collectors.toList());
//串行流有序输出
collect.stream().forEach(System.out::print);//输出 12345678910
//并行流使用多线程(占用cpc),拆分多个任务,最后再组合起来,提升效率
collect.parallelStream().forEach(System.out::print); //输出76891034152
性能比较
public static void main(String[] args) {
List<Double> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
list.add(Math.random());
}
long stime = System.currentTimeMillis();
list.parallelStream().forEach(
x->
{ String a = String.valueOf(x);
a.replace("1","0");
}
);
list.stream().forEach(
x->
{ String a = String.valueOf(x);
a.replace("1","0");
}
);
for (Double aDouble : list) {
String a = String.valueOf(aDouble);
a.replace("1","0");
}
long etime = System.currentTimeMillis();
System.out.printf("执行时长:%d 毫秒.", (etime - stime));
}
执行方式 |
执行时间ms |
并行 |
500 |
串行 |
1200 |
增强for |
1200 |
并行流使用场景:在数据量比较大的情况下,CPU负载本身不是很高,不要求顺序执行的时候,可以使用并行流
关于并行流和串行流有关api使用
方法 |
描述 |
boolean isParallel() |
判断是否是并行流 |
S sequential() |
并行流转换成串行流 |
S parallel() |
串行流转换成并行流 |
S unordered() |
将流改为无序,但不改变流类型 |
forEachOrdered |
不管是串行流还是并行流都有序操作 |
forEach |
串行流有序操作,并行流无序操作 |
例子
public static void main(String[] args) {
//创建一个1~10的list
List<Integer> collect = Stream.iterate(1, x -> x + 1).limit(1000).collect(Collectors.toList());
collect.stream().isParallel();//false
collect.parallelStream().isParallel(); //true
collect.stream().forEach(System.out::print);//12345678910
collect.parallelStream().forEach(System.out::print);//76819102543
collect.stream().forEachOrdered(System.out::print);//12345678910
collect.stream().forEachOrdered(System.out::print);//12345678910
collect.stream().unordered().forEach(System.out::println);
}
unordered()操作不会执行任何操作来显式地对流进行排序。它的作用是消除了流必须保持有序的约束,从而允许后续操作使用不必考虑排序的优化(不会打乱顺序,而是在后续操作中消除顺序的影响)。您可以在Java 8文档中阅读此内容:对于顺序流,顺序的存在与否不会影响性能,只影响确定性。如果流是顺序的,则在相同的源上重复执行相同的流管道将产生相同的结果;如果是非顺序流,重复执行可能会产生不同的结果。 对于并行流,放宽排序约束有时可以实现更高效的执行。 …在流有序时, 但用户不特别关心该顺序的情况下,使用 unordered 明确地对流进行去除有序约束可以改善某些有状态或终端操作的并行性能。