for循环与串行化、并行化Stream流性能对比

第四章 并行化Stream流

关注公众号(CoderBuff)回复“stream”获取《Java8 Stream编码实战》PDF完整版。

《Java8 Stream编码实战》的代码全部在https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/stream-coding,一定要配合源码阅读,并且不断加以实践,才能更好的掌握Stream。

在现实当中,并行化流开始并没有引起我的注意,直到我发现了它的应用场景后才发现,并行化流在提高性能以及编码难易程度上,代码bug上似乎要更胜一筹。

“第三章 Stream流”一直介绍的是串行化的流,串行化的流如果你有心可以和for循环对比,会发现串行化的流在性能上是比for循环要差的。这也是部分人“鄙视”Stream流的一点。

4.1 并行与并发

并行,指的是在同一时刻多个任务同时执行。

并发,指的是在同一时间段多个任务交替执行。

当然,并行的执行速度更快,但并行也依赖硬件设置,因为它依赖硬件CPU是多核的场景。并发则不受限制。

parallelStream

想要把串行流转换为并行流很简单,只需要将stream修改为parallelStream,其它操作不变。

public void parallel(List<Student> students) {
    students.parallelStream()
            .map(Student::getStudentNumber)
            .collect(Collectors.toList());
}
com.coderbuff.chapter4_parallelstream.ParallelStreamDemo#parallel

Stream流的并行化操作,是一种数据并行化,流本身就擅长对数据进行运算。

当然并不是将代码里所有的串行流改为并行流就万事大吉性能翻倍了,数据少了不行,CPU核数不够也不行。所以要想真正能提高性能,还要针对实际请做测试才能得出结论。

我们分别举几个数据量不同的例子,来说明for循环、串行化Stream流、并行化Stream流的性能在我本机的性能。

我测试了9个学生、90个学生、9000个学生、90000个学生后,三者的性能表现如下图所示:

com.coderbuff.chapter4_parallelstream.PerformanceTests
操作 | 9个学生 | 90个学生 | 900个学生 | 9000个学生 | 90000个学生 | 900000个学生
---|---|---|---|---|---|---|---
for循环 | 0ms | 0ms | 2ms | 8ms | 41ms | 343ms
串行化Stream | 61ms | 1ms | 2ms | 4ms | 27ms | 789ms
并行化Stream | 4ms | 0ms | 4ms | 3ms | 88ms | 358ms

从曲线图可以看出90000个学生以前3者的性能都是几毫秒,并没有太大区别,从90000个学生过后,串行化流性能主键走弱,并行化流的性能开始逐渐赶上for循环,但注意这并不意味着从900000个数据后并行化的数据就一定会超越for循环。由于后两组测试数据比较大,我们去掉90000和900000这两组数据的性能曲线图。

从这张图可以看到,串行化流在数据量很小的情况下,性能最差。而并行化流则处于波动的状态。

所以单单从数据量上可以看出:

for循环的性能随着数据量的增加性能也越来越差。

串行化流则在数据量小的情况下性能差,数据量中、大的时候性能略高于for循环,但当数据量特别大时,性能也变得越差。

并行化流受CPU核数的影响,在本机2核下,在数据量小的情况下性能略高于串行化流,略低于for循环,在数据量中的情况下差不多,在数据量比较大时性能最差,但当数据量特别大时,性能也变得更好。

如果想要使用parallelStream想提高性能,一定要根据实际情况做好测试,因为并行化的流性能不一定比串行化流性能高

关注公众号(CoderBuff)回复“stream”抢先获取PDF完整版。

近期教程:

《ElasticSearch6.x实战教程》

《Redis5.x入门教程》

《Java8 编码实战》

一个能给程序员加buff的公众号 (CoderBuff)
不积跬步,无以至千里;不积小流,无以成江海。
posted @ 2020-03-26 21:36  OKevin  阅读(3203)  评论(0编辑  收藏  举报