Stream的並行計算

一、Stream並行計算體驗,利用多核加快計算速度

stream的併發,多個cpu執行同一個任務,提高效率;

需求:從1+...+10000000,看下各種計算方法的運行時間是多少

 

代碼例子如下:

  1 package com.cy.java8;
  2 
  3 import java.util.function.Function;
  4 import java.util.stream.LongStream;
  5 import java.util.stream.Stream;
  6 
  7 public class ParallelProcessing {
  8 
  9     public static void main(String[] args) {
 10         //查看計算機核心線程數
 11         //System.out.println(Runtime.getRuntime().availableProcessors());
 12 
 13         long fastest1 = measureSumPerformance(ParallelProcessing::normalAdd, 10000000);
 14         System.out.println("normalAdd the best processing time : " + fastest1 + " ms");
 15 
 16         long fastest2 = measureSumPerformance(ParallelProcessing::iterateStream, 10000000);
 17         System.out.println("iterateStream the best processing time : " + fastest2 + " ms");
 18 
 19         long fastest3 = measureSumPerformance(ParallelProcessing::parallelStream, 10000000);
 20         System.out.println("parallelStream the best processing time : " + fastest3 + " ms");
 21 
 22         long fastest4 = measureSumPerformance(ParallelProcessing::parallelStream2, 10000000);
 23         System.out.println("parallelStream2 the best processing time : " + fastest4 + " ms");
 24 
 25         long fastest5 = measureSumPerformance(ParallelProcessing::parallelStream3, 10000000);
 26         System.out.println("parallelStream3 the best processing time : " + fastest5 + " ms");
 27 
 28     }
 29 
 30 
 31     /**
 32      * 將下面的求和方法分別計算10次,取10次中運行最短的時間
 33      */
 34     private static long measureSumPerformance(Function<Long, Long> adder, long limit){
 35         long fastest = Long.MAX_VALUE;
 36 
 37         for(int i=0; i<10; i++){
 38             long startTime = System.currentTimeMillis();
 39             long result = adder.apply(limit);
 40             long spendTime = System.currentTimeMillis() - startTime;
 41             System.out.println("the sum result is " + result);
 42             if(spendTime < fastest){
 43                 fastest = spendTime;
 44             }
 45         }
 46         return fastest;
 47     }
 48 
 49     /**
 50      * 計算一串long類型的總和,普通的stream
 51      * @param limit
 52      * @return
 53      */
 54     private static long iterateStream(long limit){
 55         return Stream.iterate(1L, i->i+1).limit(limit).reduce(0L, Long::sum);
 56     }
 57 
 58     /**
 59      * 使用Stream.parallel
 60      * 比較慢,爲什麼?
 61      * Stream.iterate不適合並行計算
 62      */
 63     private static long parallelStream(long limit){
 64         return Stream.iterate(1L, i->i+1).parallel().limit(limit).reduce(0L, Long::sum);
 65     }
 66 
 67     /**
 68      * 將上面的Stream先自動拆箱爲long,再並行
 69      * 雖然拆箱爲LongStream,還是很慢,爲什麼?
 70      * Stream.iterate不適合並行計算
 71      */
 72     private static long parallelStream2(long limit){
 73         return Stream.iterate(1L, i -> i + 1)
 74                         .mapToLong(Long::longValue)
 75                         .parallel().limit(limit).reduce(0L, Long::sum);
 76     }
 77 
 78     /**
 79      * 使用LongStream.range
 80      * 很快,比normalAdd快了近一倍,爲什麼?
 81      * LongStream、IntStream等..它們的IntStream.range非常卓越的適合並行計算
 82      */
 83     private static long parallelStream3(long limit){
 84         return LongStream.rangeClosed(1, limit).parallel().reduce(0L, Long::sum);
 85     }
 86 
 87 
 88     /**
 89      * 以前的寫法
 90      * @param limit
 91      * @return
 92      */
 93     private static long normalAdd(long limit){
 94         long result = 0L;
 95         for(long i=0L; i <= limit; i++){
 96             result += i;
 97         }
 98         return result;
 99     }
100 }

console:

the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
normalAdd the best processing time : 3 ms
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
iterateStream the best processing time : 78 ms
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
parallelStream the best processing time : 128 ms
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
parallelStream2 the best processing time : 178 ms
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
the sum result is 50000005000000
parallelStream3 the best processing time : 0 ms

 

結論:不一定是所有的方法產生的Stream都適合於並行的方式去做的,一定要注意有些方法是對於並行是厭惡的,有些方法是喜歡並行的;

列舉一些例子如下:

數據源           分解性能
Source           Decomposability
ArrayList           Excellent
LinkedList           Poor
IntStream.range        Excellent
Stream.iterate         Poor
HashSet             Good
TreeSet              Good

 

二、Fork Join    

 

 

 

 

----

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章