JDK8 | 串行流 Stream 与并行流 parallelStream
一、串行 Stream 流
1.获取串行流的两种方式:
所有的 Collection 集合都可以通过 stream 默认方法获取流:list.stream();Stream 接口的静态方法 of 可以获取数组对应的流:Stream.of(6,1,5,4,3);
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
<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
));
}
@Test
public void parallelStream() {
System
.out
.println("serialStream");
LongStream
.rangeClosed(0, times
).parallel().reduce(0, Long
::sum
);
}
@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.注意事项
parallelStream是线程不安全的parallelStream适用的场景是CPU密集型的,只是做到别浪费CPU,假如本身电脑CPU的负载很大,那还到处用并行流,那并不能起到作用I/O密集型 磁盘I/O、网络I/O都属于I/O操作,这部分操作是较少消耗CPU资源,一般并行流中不适用于I/O密集型的操作,就比如使用并流行进行大批量的消息推送,涉及到了大量I/O,使用并行流反而慢了很多在使用并行流的时候是无法保证元素的顺序的,也就是即使你用了同步集合也只能保证元素都正确但无法保证其中的顺序