Stream(流)简介
Stream(流)是Java8新增对集合处理的抽象概念,类似于数据库结构化查询语句(SQL),使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。
集合可以通过stream()方法创建串行流(元素一个接一个串行处理),parallelStream()方法创建并行流(多个元素可同时进行处理)。
parallelStream集合处理效率
案例说明
代码如下:
public class StreamTest {
public static void main(String[] args) {
System.out.println("CPU核数:num=" + Runtime.getRuntime().availableProcessors() + "\n");
List list = IntStream.range(0,10).boxed().collect(Collectors.toList());
long startTime = System.currentTimeMillis();
System.out.println(list.stream().map(StreamTest::format).collect(Collectors.toList()));
System.out.println("stream() time=" + (System.currentTimeMillis() - startTime) + "\n");
startTime = System.currentTimeMillis();
System.out.println(list.parallelStream().map(StreamTest::format).collect(Collectors.toList()));
System.out.println("parallelStream() time=" + (System.currentTimeMillis() - startTime));
}
public static Integer format(Integer i) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
return i+1;
}
}
执行结果:
CPU核数:num=4
*** stream()方法数据串行执行,执行时间等于每个集合元素处理时间之和 ***
main
main
main
main
main
main
main
main
main
main
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
stream() time=1031
*** parallelStream()方法数据并行执行,执行时间约等于所有每个集合元素处理时间之后/CPU核数 ***
ForkJoinPool.commonPool-worker-1
main
ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-3
main
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-3
main
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
parallelStream() time=312
说明:
1,parallelStream使用ForkJoinPool线程池处理任务
2,ForkJoinPool默认线程池大小为CPU核数-1(注:主线程也负责处理任务),不建议修改该大小
线程池(ForkJoinPool)
分治法
image.png
说明:
Fork/Join框架的核心思想是采用分治法的思想。分治法:将一个复杂的问题拆分成若干个规模较小,相对独立但问题类型相同的子问题进行处理,然后再将子问题的结果合并成原始问题的完整答案。这样的问题处理策略就叫分治法。分治法三个关键步骤:1,问题拆分;2,子问题计算;3,合并。
采用分治法可以有效利用多核CPU的优势,把子问题通过并行计算,提高整体性能。
工作窃取算法
image.png
说明:
工作窃取(work-stealing)算法是Fork/Join框架的核心理念,指当某个处理线程空闲后,为了合理利用CPU资源,就从其他线程的任务队列里面窃取任务来执行,这样能减少CPU空闲等待时间,提高空闲CPU的利用率。
注意事项
1,parallelStream()是线程不安全的
2,parallelStream()是以充分使用CPU资源来提升效率,不在多线程种使用
3,parallelStream()确保每个处理是无状态且没有关联的
总结思考
优缺点
优点
1,成倍提升集合处理效率,提高系统性能(TPS/QPS)
缺点
1,线程不安全,需要正确合理使用(解决方法:加锁、使用线程安全的集合或者采用collect()或者reduce()操作)
parallelStream适用场景
1,计算密集型集合处理(合理使用多核CPU的优势)