当前位置: 首页 > 科技观察

你破坏Java代码的方式太美了!

时间:2023-03-16 16:53:39 科技观察

本文转载自微信公众号“小明菜市场”,作者小明菜市场。转载本文请联系小明菜市场公众号。前言如果之前需要对一个集合进行处理,需要手动将其分成几个部分,然后为每个部分创建一个线程,最后在合适的时候进行合并。这是一种手动处理并行集合的方法。在java8中,有一个新功能,可以开启并行模式。并行流的识别启用并行流什么是并行流?它是一种流,将一个流内容分成多个数据块,并使用不同的线程分别处理每个不同的数据块。例如,下面有一个例子。在List中,需要单独计算List数据。代码如下:ListappleList=newArrayList<>();//假装从库中检出数据for(Appleapple:appleList){apple.setPrice(5.0*apple.getWeight()/1000);}这里,时间复杂度是O(list.size)。随着列表的增加,时间消耗也随之增加。并行流可以解决这个问题,代码如下:appleList.parallelStream().forEach(apple->apple.setPrice(5.0*apple.getWeight()/1000));这里,通过调用parallelStream()流,将当前流并行,然后并行执行。并行流内部使用默认的ForkJoinPool线程池,默认的线程数为处理器的核心数。测试并行流的常用代码如下:publicstaticvoidmain(String[]args)throwsInterruptedException{ListappleList=initAppleList();Datebegin=newDate();for(Appleapple:appleList){apple.setPrice(5.0*apple.getWeight()/1000);Thread.sleep(1000);}Dateend=newDate();log.info("苹果个数:{},耗时:{}s",appleList.size(),(end.getTime()-begin.getTime())/1000);}输出耗时4s。并行代码如下:ListappleList=initAppleList();Datebegin=newDate();appleList.parallelStream().forEach(apple->{apple.setPrice(5.0*apple.getWeight()/1000);try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}});Dateend=newDate();log.info("苹果数量:{},耗时:{}s",appleList.size(),(end.getTime()-begin.getTime())/1000);输出结果耗时1s。可以看到,耗时有了很大的提升,提升了3s。并行流拆分会影响流的速度。对于并行流,需要注意以下几点:对于iterate方法处理的前n个数,无论并行与否,总是比循环慢,对于LongStream。rangeClosed()方法,没有迭代的第二个痛点。它生成基本类型的值,无需拆箱操作。此外,它还可以直接将待生成的数1-n拆分为1-n/4、1n/4-2n/4、……3n/4-n等四部分。因此,并行状态下的rangeClosed()比for循环的外部迭代要快。代码如下:packagelambdasinaction.chap7;importjava.util.stream.*;publicclassParallelStreams{publicstaticlongiterativeSum(longn){longresult=0;for(longi=0;i<=n;i++){result+=i;}returnresult;}publicstaticlongsequentialSum(longn){returnStream.iterate(1L,i->i+1).limit(n).reduce(Long::sum).get();}publicstaticlongparallelSum(longn){returnStream.iterate(1L,i->i+1).limit(n).parallel().reduce(Long::sum).get();}publicstaticlongrangedSum(longn){returnLongStream.rangeClosed(1,n).reduce(Long::sum).getAsLong();;}}packagelambdasinaction.chap7;importjava.util.concurrent.*;importjava.util.function.*;publicclassParallelStreamsHarness{publicstaticfinalForkJoinPoolFORK_JOIN_POOL=newForkJoinPool();publicstaticvoidmain(String[]args){System.out.println("IterativeSumdoneinmeasurePerf(ParallelStreams::它erativeSum,10_000_000L)+"msecs");System.out.println("SequentialSumdonein:"+measurePerf(ParallelStreams::sequentialSum,10_000_000L)+"msecs");System.out.println("ParallelforkJoinSumdonein:"+measurePerf(ParallelStreams::parallelSum,10_000_000L)+"msecs");System.out.println("RangeforkJoinSumdonein:"+measurePerf(ParallelStreams::rangedSum,10_000_000L)+"msecs");System.out.println("ParallelrangeforkJoinSumdonein:"+measurePerf(ParallelStreams::parallelRangedSum,10_000_000L)+"msecs");}publicstaticlongmeasurePerf(Functionf,Tinput){longfastest=Long.MAX_VALUE;for(inti=0;i<10;i++){longstart=System.nanoTime();Rresult=f.apply(input);longduration=(System.nanoTime()-start)/1_000_000;System.out.println("Result:"+result);if(duration