JDK8 | 串行流 Stream 與並行流 parallelStream
一、串行 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.注意事項
- parallelStream是線程不安全的
- parallelStream適用的場景是CPU密集型的,只是做到別浪費CPU,假如本身電腦CPU的負載很大,那還到處用並行流,那並不能起到作用
- I/O密集型 磁盤I/O、網絡I/O都屬於I/O操作,這部分操作是較少消耗CPU資源,一般並行流中不適用於I/O密集型的操作,就比如使用並流行進行大批量的消息推送,涉及到了大量I/O,使用並行流反而慢了很多
- 在使用並行流的時候是無法保證元素的順序的,也就是即使你用了同步集合也只能保證元素都正確但無法保證其中的順序