当前位置: 首页 > 后端技术 > Java

请停止使用parallelStream,它比Stream还要慢!!

时间:2023-04-01 15:30:55 Java

parallelStream一定更快吗?大家都知道Stream分为sequentialstream和parallelstream:stream(顺序流)parallelStream(并行流)它们最大的区别就是parallelStream支持并行处理,所以效率肯定比stream(顺序流)快。本文不会介绍Stream的基础知识。之前在Stream系列写过一个话题。不懂的可以关注公众号Java技术栈,然后在公众号Java教程菜单中阅读。但是你确定parallelStream一定更快吗?栈长写了一个排序的例子,使用stream和parallelStream对一个100~10000000条数据的集合进行排序,来看看执行效率如何!顺序流排序:/***顺序流排序*@author:stacklength*@from:公众号Java技术栈*/privatestaticvoidstreamSort(){longstart=System.currentTimeMillis();Listlist=newArrayList<>(LIST);list.stream().sorted(SortTest.User::compareAge).collect(Collectors.toList());System.out.println("\nListsize:"+list.size()+"Stream.sorted:"+(System.currentTimeMillis()-start));}并行流排序:/***并行流排序*@author:stacklength*@from:公众号Java技术栈*/privatestaticvoidparallelStreamSort(){longstart=System.currentTimeMillis();Listlist=newArrayList<>(LIST);list.parallelStream().sorted(SortTest.User::compareAge).collect(Collectors.toList());System.out.println("Listsize:"+list.size()+"ParallelStream.sorted:"+(System.currentTimeMillis()-start));}本文全部内容完整示例源码已上传:https://github.com/javastacks...执行结果如下:Listsize:10000000Stream.sorted:202Listsize:10000000ParallelStream.sorted:402Listsize:1000000Stream.排序:53列表大小:1000000ParallelStream.sorted:15列表大小:100000Stream.sorted:1列表大小:100000ParallelStream.sorted:2列表大小:10000Stream.sorted:0列表大小:10000ParallelStream.sorted:1列表大小:1000Stream.sorted:0Listsize:1000ParallelStream.sorted:1Listsize:100Stream.sorted:0Listsize:100ParallelStream.sorted:0100000以下无差异;ParallelStream在大约1,000,000时领先于Stream,但并非每次都如此。经过不断的测试,这个在数据量区间的测试中,两者会遥遥领先;它非常稳定在10000000左右,ParallelStream几乎比Stream慢2倍!现在你可能想知道,为什么会这样?栈长一开始也有疑惑,并行流(ParallelStream)怎么会比顺序流(Stream)慢。其实想想就明白了。并行流(ParallelStream)背后其实是Java7开始支持的Fork/Join,即将一个大任务拆分成N个小任务,最后合并每个子任务的结果,所以进行拆分、创建、合并等操作子任务线程的结果需要很大的开销,尤其是线程的创建。因此,这种并不耗时的简单排序操作其实并不适合并行流(ParallelStream),它带来的线程创建损失可能比顺序流(Stream)要慢。最新的Java8+面试题也整理好了,点击Java面试库小程序在线刷题。何时使用ParallelStream?由于使用Fork/Join是有损的,理论上单条数据的处理时间应该超过并行流(ParallelStream)本身的损失,这种情况下比较合适。也就是说,如果流中每条数据的处理都比较耗时,而且没有顺序要求,那么在这种场景下使用并行流(ParallelStream)会更快更合适。我们看下面的例子:顺序流数据处理:/***顺序流数据处理*@author:stacklength*@from:公众号Java技术栈*/privatestaticvoidstreamProcess(){longstart=System.当前时间毫秒();Listlist=newArrayList<>(LIST);list.stream().map(StreamSpeedTest::process).collect(Collectors.toList());System.out.println("\n列表大小:"+list.size()+"流处理:"+(System.currentTimeMillis()-start));}并行流数据处理:/***并行流数据处理*@author:stacklength*@from:公众号Java技术栈*/privatestaticvoidparallelStreamProcess(){longstart=System.currentTimeMillis();Listlist=newArrayList<>(LIST);list.parallelStream().map(StreamSpeedTest::process).collect(Collectors.toList());System.out.println("列表大小:"+list.size()+"并行流进程:"+(System.currentTimeMillis()-start));}数据处理:/***数据处理*@author:栈长*@from:公众号Java技术栈*/privatestaticSortTest.Userprocess(SortTest.Useruser){try{user.setName(user.getName()+":process");线程.睡眠(5);}catch(InterruptedExceptione){e.printStackTrace();}returnuser;}注意:这里添加了5毫秒的休眠。为了反映数据的真实处理时间,本文所有完整示例源码均已上传:https://github.com/javastacks...并行流排序:Listsize:1000Streamprocess:5750Listsize:1000ParallelStreamprocess:745Listsize:100Streamprocess:566Listsize:100ParallelStreamprocess:77结果很明显,无论你测试多少次,并行流(ParallelStream)的处理速度都比顺序流(Stream)快)次!!我这里只测试了100条和1000条数据,因为使用顺序流(Stream)可能等待10000条以上的数据需要很长时间。而且,我程序中的处理逻辑只休眠了5毫秒。如果实际处理单条数据的时间比这个长,并行流(ParallelStream)的处理效率会更加明显。总结简单总结一下:stream:适用于避免线程安全问题,需要顺序执行,数据处理简单,不耗时的任务;parallelStream:适用于不存在线程安全问题、不需要顺序执行、需要耗时数据处理的任务;那么,你学业有失了吗?赶快发给身边的同事吧,别再乱用parallelStream了!如果用不好,不说线程安全问题,在效率上可能会适得其反。如果不知道如何使用Java8的新知识点(Lambda、Stream、函数式接口等),可以关注公众号:Java技术栈,在Java教程菜单里看,我写过Java8+系列教程的有一堆。本文所有完整示例源码均已上传:https://github.com/javastacks...欢迎Star学习,这??里将提供以下Java示例!好了,今天的分享就到这里。稍后栈长会分享更多有趣的Java技术和最新的技术资料。关注公众号Java技术栈第一时间推送。我也会分享主流的Java面试题和参考答案。全部搞定后在公众号后台回复关键词“面试”刷题。最后,如果觉得我的文章对你有用,动动你的小手,送给正在看的人,转发吧,原创不易,楼主需要你的鼓励。版权声明:本文为公众号《Java技术栈》原创。转载、引用本文内容请注明出处。抄袭、洗稿均属侵权投诉,后果自负,并保留追究法律责任的权利。近期热点文章推荐:1.1000+Java面试题及答案(2022最新版)2.厉害了!Java协程来了。..3.SpringBoot2.x教程,太全面了!4.不要用爆破爆满画面,试试装饰者模式,这才是优雅的方式!!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!