並行流計算--統計1-n的和,計算密集型
import java.util.function.Function; import java.util.stream.LongStream; import java.util.stream.Stream; public class ParalleStreamDemo { public static long parallelSum(long n) { return Stream.iterate(1L, i -> i+1) .limit(n) .parallel() .reduce(0L, Long::sum); } public static long sequenceSum(long n) { return Stream.iterate(1L, i -> i+1) .limit(n) .reduce(0L, Long::sum); } public static long iterativeSum(long n) { long result = 0; for(int i = 0; i < n; i++) { result =+ i; } return result; } public static long parallelSum2(long n) { return LongStream.rangeClosed(0, n).parallel().reduce(0, Long::sum); } public static long sequenceSum2(long n) { return LongStream.rangeClosed(0, n).reduce(0, Long::sum); } public static long test(Function<Long, Long> computer, long n) { long fastest = Long.MAX_VALUE; for(int i = 0; i < 100; i++) { long start = System.currentTimeMillis(); computer.apply(n); long cost = System.currentTimeMillis() - start; if( cost < fastest) { fastest = cost; } } return fastest; } public static void run1(long n) { System.out.println("順行流"+test(ParalleStreamDemo::sequenceSum, n)); System.out.println("並行流"+test(ParalleStreamDemo::parallelSum, n)); System.out.println("迭代"+test(ParalleStreamDemo::iterativeSum, n)); } public static void run2(long n) { System.out.println("順行流2"+test(ParalleStreamDemo::sequenceSum2, n)); System.out.println("並行流2"+test(ParalleStreamDemo::parallelSum2, n)); System.out.println("迭代2"+test(ParalleStreamDemo::iterativeSum, n)); } public static void main(String[] args) { long n = 20_000_000; run1(n); run2(n); } }
run1執行結果:
順行流174
並行流628
迭代13
分析:
1.iterate很難分成獨立的小塊,它每一次呼叫函式都依賴上一次的結果,整個數字列表最初計算的時候還沒準1備好。它使用的是連結串列,而非陣列。
2.java8在java7的分支合併框架的基礎上打造。
3.iterate方法它生成的東西是裝箱物件Long,需要再拆箱。
正確使用並行流:
順行流29
並行流24
迭代213
並行過程本身需要對每個過程做地域劃分,把每個子流的歸納操作分配給不同的執行緒,然後合併成一個值,這些jdk背後做的。再多個核心直接移動資料的代價是比較大的。所以我們要保證再一個核心中執行的時間要大於核心間傳遞資料的時間。