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毫秒,所以使用合适的数据结构比无脑的使用并行更有用.