Java新特性玩转JDK8之并行流parallelStream
为什么会有这个并行流?
-
集合做重复的操作,如果使用串行执行会相当耗时,因此一般会采用多线程来加快, Java8的paralleStream用fork/join框架提供了并发执行能力
-
底层原理
- 线程池(ForkJoinPool)维护一个线程队列
- 可以分割任务,将父任务拆分成子任务,完全贴合分治思想
stream和parallelStream区别
public class Main {
public static void main(String[] args) {
//顺序输出 123456789
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.stream().forEach(System.out::print);
System.out.println();//换行
//并行乱序输出 比如 658974132 此输出不固定
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
nums.parallelStream().forEach(System.out::print);
}
}
``
### 问题
- paralleStream并行 是否一定比 Stream串行 快?
- 错误,数据量少的情况,可能串行更快,ForkJoin会耗性能
- 多数情况下并行比串行快,是否可以都用并行?
- 不行,部分情况会有线程安全问题,parallelStream里面使用的外部变量,比如集合一定要使用线程安全集合,不然就会引发多线程安全问题
<a name="fVQ7l"></a>
### 多线程安全问题
- 比如:对没有线程安全的List集合进行添加操作,会出现问题。
- 代码
```java
public class Main {
public static void main(String[] args) {
for (int i=0;i<2;i++) {
ArrayList<Integer> integers = new ArrayList<>();
IntStream.range(0, 100).parallel().forEach(integers::add);
System.out.println(integers);
}
}
}
- 测试结果
- null 值问题
- 直接报错
- null 值问题
- 解决方案
- 使用类 java.util.concurrent.CopyOnWriteArrayList 替代ArrayList
- 代码
- 使用类 java.util.concurrent.CopyOnWriteArrayList 替代ArrayList
public class Main {
// 此时无任何异常
public static void main(String[] args) {
for (int i=0;i<2;i++) {
CopyOnWriteArrayList<Integer> integers = new CopyOnWriteArrayList<>();
IntStream.range(0, 100).parallel().forEach(integers::add);
System.out.println(integers);
}
}
}
未经授权不得转载或转载请注明出处