找回密码
 会员注册
查看: 37|回复: 0

Java多线程之并行流(parallelStream)

[复制链接]

4

主题

0

回帖

13

积分

新手上路

积分
13
发表于 2024-9-3 18:48:10 | 显示全部楼层 |阅读模式
文章目录一、概述二、使用方法2.1parallelStream使用2.2Stream方法介绍2.3简单示例三、应用示例3.1示例介绍3.2简单任务测试结果3.3复杂任务测试结果3.4结论四、完整示例一、概述并行流是Java中StreamAPI的一部分,用于在多核处理器上并行执行流操作。在Java8及更高版本中引入的StreamAPI提供了一种新的处理集合的方式,使得开发者能够更轻松地进行数据处理和操作。在使用StreamAPI时,可以将集合转换为流,然后进行各种操作,例如过滤、映射、排序等。在这个过程中,流可以是串行流(SequentialStream)或并行流(ParallelStream)。并行流通过使用多线程并行处理数据,充分利用多核处理器的优势,从而在某些情况下提高处理速度。使用并行流非常简单,只需在流上调用parallel()方法即可将其转换为并行流。其实本质上是使用线程池FrorkJoinPool。本文后面将通过测试来说明实际应用场景应该如何选择并行流。但是可能我的测试有局限性,如果有任何错误欢迎大家指正。二、使用方法2.1parallelStream使用使用方法就是调用集合的parallelStream()方法转为并行流,然后再使用stream执行后续计算就是并行计算(使用线程池)。Listlist=newArrayList();Streamstream=List.parallelStream()122.2Stream方法介绍使用parallelStream对集合进行并行操作,类似于普通的串行流操作,主要方法如下:forEach方法,对流中的每个元素执行指定的操作,可以并行执行。如下调用System.out.println输出显示list每个元素。Listlist=Arrays.asList("apple","banana","orange");list.parallelStream().forEach(System.out::println);//System.out::println是System.out.println的Lambda写法12filter方法,使用给定的条件过滤流中的元素。如下筛选出偶数并输出显示。Listnumbers=Arrays.asList(1,2,3,4,5,6,7,8,9,10);numbers.parallelStream().filter(n->n%2==0).forEach(System.out::println);//n->n%2==0是Lambda写法,相当于一个函数boolf(intn){returnn%2==0;}12map方法,将流中的每个元素映射到另一个值。如下把每个元素转成大写。Listwords=Arrays.asList("apple","banana","orange");words.parallelStream().map(String::toUpperCase).forEach(System.out::println);12reduce方法,使用给定的累积函数进行归约操作。如下,进行求和操作Listnumbers=Arrays.asList(1,2,3,4,5);intsum=numbers.parallelStream().reduce(0,Integer::sum);System.out.println("求合结果:"+sum);123collect方法,将流中的元素收集到一个集合中。如下将并行计算结果存储到uppercaseWords变量中。Listwords=Arrays.asList("apple","banana","orange");ListuppercaseWords=words.parallelStream().map(String::toUpperCase).collect(Collectors.toList());12anyMatch和allMatch方法anyMatch用于判断流中是否有任意一个元素匹配给定条件allMatch用于判断流中的所有元素是否都匹配给定条件。Listnumbers=Arrays.asList(1,2,3,4,5,6);booleananyEven=numbers.parallelStream().anyMatch(n->n%2==0);//只要有一个是偶数就是为真booleanallEven=numbers.parallelStream().allMatch(n->n%2==0);//必须全部是偶数才为真123这些方法在串行流中可以使用用,在并行流中可以充分发挥多核处理器的优势。请注意,使用并行流时需要确保操作是无状态的,以避免并发问题。在实际应用中,可以根据任务的性质和数据规模选择适当的流类型。2.3简单示例下面是一个简单的示例,演示集合并行流的使用privatestaticvoidtest1(){Listlist=Arrays.asList("apple","banana","orange","grape","peach");//串行流操作(单线程,效率低)list.stream().map(String::toUpperCase).forEach(System.out::println);System.out.println("---------");//并行流操作(多线程,效率高)list.parallelStream().map(String::toUpperCase).forEach(System.out::println);}123456789101112131415在这个示例中,关键是看list.parallelStream(),使用他创建了一个并行流。然后使用map方法将元素转换为大写,然后通过forEach方法打印出来。String::toUpperCase是Lambda写法(同“xxxx”.toUpperCase),结合map,相当于对集合中的每一个元素进行一次toUpperCase(转大写)System.out::println也是Lambda写法(同System.out.println(“xxxx”)),结合forEach,相当于对集合中的每个元素进行打印显示。并不是所有情况下都应该使用并行流,因为在某些场景下,多线程的开销可能会超过并行执行所带来的性能提升。选择使用串行流还是并行流应该根据实际情况和性能测试来进行权衡。在某些情况下,使用并行流可以有效提高处理速度,但在其他情况下,串行流可能更为合适。三、应用示例3.1示例介绍在接下的示例中我,准备随机生成1千万个随机数,然后第使用for循环、串行流、并行流这三种方法找出数字为250的数。以此来检查运行效率。生成数据代码privatestaticlongDATA_COUNT=1000_0000;Listlist=newArrayList();for(inti=0;iresult=newArrayList();for(inti=0;i250&valresult=list.stream().filter((val)->{//sleep(1);returnval>250&valresult=list.parallelStream().filter((val)->{//sleep(1);returnval>250&vallist=newArrayList();for(inti=0;ilist=Arrays.asList("apple","banana","orange","grape","peach");//串行流操作(单线程)list.stream().map(String::toUpperCase).forEach(System.out::println);System.out.println("---------");//并行流操作(多线程)list.parallelStream().map(String::toUpperCase).forEach(System.out::println);}privatestaticlongtest2(Listlist){longstartTime=System.currentTimeMillis();Listresult=newArrayList();for(inti=0;i250&vallist){longstartTime=System.currentTimeMillis();Streamresult=list.stream().filter((val)->{sleep(1);returnval>250&val{System.out.println(val);});longendTime=System.currentTimeMillis();returnendTime-startTime;}privatestaticlongtest4(Listlist){longstartTime=System.currentTimeMillis();Streamresult=list.parallelStream().filter((val)->{sleep(1);returnval>250&val{System.out.println(val);});longendTime=System.currentTimeMillis();returnendTime-startTime;}privatestaticvoidsleep(longms){try{Thread.sleep(ms);}catch(InterruptedExceptione){e.printStackTrace();}}}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-13 10:48 , Processed in 1.228597 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表