1.並行流並不一定能提高效率,就和多線程並不能提高線程的效率一樣
因為引入並行流會引起額外的開銷,就像線程的頻繁上下文切換會導致額外的性能開銷一樣,當數據在多個cpu中的處理時間小於內核之間的傳輸時間,使用並行流也就沒有什么意義了.
這邊用代碼演示一下
public static long iterativeSum(long n) { long result = 0; for (long i = 1L; i <=n; i++) { result += i; } return result; }
public static long parallelSum(long n){ return Stream.iterate(1L, i -> i+1) .limit(n) .parallel() .reduce(0L, Long::sum); }
第一個是我們經常使用的for循環,第二個是使用LongStream生成long類型的流,並且通過 parallel並行化,我們看看執行結果
package demo13; import java.util.function.Function; public class PerformanceClass { public static long measureSumPerf(Function<Long, Long> adder, long n) { long fastest = Long.MAX_VALUE; for (int i = 0; i < 10; i++) { long start = System.nanoTime(); long sum = adder.apply(n); System.out.println("Result: "+ sum); long duration = (System.nanoTime() - start) / 1_000_000; if (duration < fastest) { fastest = duration; } } return fastest; } public static void main(String[] args) { System.out.println(measureSumPerf(ParalleStreams::iterativeSum, 10_000_000));//3 System.out.println(measureSumPerf(ParalleStreams::parallelSum, 10_000_000));//173 // System.out.println(measureSumPerf(ParalleStreams::sequentialSum, 10_000_000)); // System.out.println(measureSumPerf(ParalleStreams::rangedSum, 10_000_000)); // System.out.println(measureSumPerf(ParalleStreams::parallelRangedSum, 10_000_000)); // System.out.println(measureSumPerf(ParalleStreams::sideEffectSum, 10_000_000)); } }
上面只是一個測試代碼,我們看到for使用了 3毫秒,但是 並行流竟然使用了 173毫秒,所以parallel並不一定能提高效率
2.這邊我們可以使用LongStream來直接生成long類型的數據來避免拆裝箱
public static long rangedSum(long n) { return LongStream.rangeClosed(1, n).reduce(0L, Long::sum); }
System.out.println(measureSumPerf(ParalleStreams::rangedSum, 10_000_000));//4
上面並行之所以慢是因為數據要進行拆箱裝箱操作,所以用LongStream替代Stream就可以提升程序的效率.
這邊只使用了4毫秒,所以使用合適的數據結構比無腦的使用並行更有用.