JDK8 | 串行流 Stream 与并行流 parallelStream
简述:在创建Stream流对象时,默认创建都是串行流。两种方式创建Stream并行流:第1种方式是通过Collection集合接口中的parallelStream()方法直接将集合类型的源数据转变为Stream并行流;第2种方式通过BaseStream接口中的parallel()方法将Stream串行流转变为并行流。BaseStream接口还提供了isParallel()方法,用于判断当Stream流对象是否为并行流,返回值为boolean类型。
一、串行 Stream 流
1.获取串行流的两种方式:
所有的 Collection 集合都可以通过 stream 默认方法获取流:list.stream();
Stream 接口的静态方法 of 可以获取数组对应的流:Stream.of(6,1,5,4,3);
// 集合获取流
// Collection接口中的方法: default Stream<E> stream() 获取流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Vector<String> vector = new Vector<>();
Stream<String> stream3 = vector.stream();
// Map获取流
Map<String, String> map = new HashMap<>();
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.values().stream();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
2.Stream常用方法,其他方法大家自行查阅官方API文档
3.Stream注意事项(重要)
Stream只能操作一次
Stream方法返回的是新的流
Stream不调用终结方法,中间的操作不会执行
二、并行 parallelStream 流
1.获取并行流的两种方式:
直接获取并行的流:
将串行流转成并行流:
// 直接获取并行的流
ArrayList<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.parallelStream();
// 将串行流转成并行流
ArrayList<Integer> list2 = new ArrayList<>();
Stream<Integer> stream = list2.stream().parallel();
2.并行流的效率是要比串行流要高,底层使用Fork/Join框架进行处理
测试效率
public class Demo {
private static long times = 50000000000L;
private long start;
@Before
public void init() {
start = System.currentTimeMillis();
}
@After
public void destory() {
long end = System.currentTimeMillis();
System.out.println("消耗时间: " + (end - start));
}
// 测试效率,parallelStream 122
@Test
public void parallelStream() {
System.out.println("serialStream");
LongStream.rangeClosed(0, times).parallel().reduce(0, Long::sum);
}
// 测试效率,普通Stream 354
@Test
public void serialStream() {
System.out.println("serialStream");
LongStream.rangeClosed(0, times).reduce(0, Long::sum);
}
}
3.解决并行流的线程安全问题:多线程下,使用并行流会有线程安全的问题
根据需要进行不同的处理:
使用同步代码块 synchronized (比如使用forEach循环处理时)
使用线程安全的集合 Vector、Collections.synchronizedList(list)
调用Stream流的 collect/toArray 方法
4.注意事项
1.parallelStream是线程不安全的。
2.parallelStream适用的场景是CPU密集型的,只是做到别浪费CPU,假如本身电脑CPU的负载很大,那还到处用并行流,那并不能起到作用。I/O密集型 磁盘I/O、网络I/O都属于I/O操作,这部分操作是较少消耗CPU资源,一般并行流中不适用于I/O密集型的操作,就比如使用并流行进行大批量的消息推送,涉及到了大量I/O,使用并行流反而慢了很多。
3.在使用并行流的时候是无法保证元素的顺序的,也就是即使你用了同步集合也只能保证元素都正确但无法保证其中的顺序。