stream和parallelStream是Java8新增的特性,用于集合流式处理,正常stream用的比较多,数据量多时使用parallelStream可以启用多线程处理,用的好没问题,用不好就坑爹了。
项目过程中就遇到了这种问题,记录下防止下次出错,使用parallelStream时,要特别小心集合线程安全性。
public static void main(String[] args) {
long start = System.currentTimeMillis();
List<Student> list1 = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list1.add(new Student(i, String.valueOf(i)));
}
List<Student> list2 = Collections.synchronizedList(new ArrayList<>());
// List<Test11> list2 =new LinkedList<>();
list1.parallelStream().forEach(item -> {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list2.add(new Student(item.getAge(), item.getName()));
});
list2.forEach(item -> {
});
long end = System.currentTimeMillis();
System.out.println(end - start);
System.out.println(list2.size());
}
上面代码没问题,遍历list1,往list2添加,list2使用Collections.synchronizedList定义,保证线程安全性。
执行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java -
1524
10000
Process finished with exit code 0
不用Collections.synchronizedList,直接定义new LinkedList,会报错:
/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java -
Exception in thread "main" java.lang.NullPointerException
at java.util.LinkedList$ListItr.next(LinkedList.java:893)
at java.lang.Iterable.forEach(Iterable.java:74)
at com.wozaijia.dev.tool.Test.main(Test.java:41)
Process finished with exit code 1
坑爹玩意,以后遇到集合并发要特别注意。