并行流个人工作中用处很少,所以仅仅了解了一下,详细的可以自己去看《Java 8 实战》
parallel
将序流转为并行流。并行流内部是使用了Fork/Join框架去做处理。
sequential
将并行流转为顺序流。
先看一个小测试
long start2 = System.nanoTime();
long sum2 = LongStream.rangeClosed(1, 500000000).parallel().reduce(0L, Long::sum);
long duration2 = (System.nanoTime() - start2) / 1_000_000;
System.out.println("并行耗时:" + duration2);
System.out.println(sum2);
long start = System.nanoTime();
long sum = LongStream.rangeClosed(1, 500000000).reduce(0L, Long::sum);
long duration = (System.nanoTime() - start) / 1_000_000;
System.out.println("耗时:" + duration);
System.out.println(sum);
最终的执行结果是
并行耗时:148
125000000250000000
耗时:845
125000000250000000
并行流确实可以提高计算效率 。然而使用并行流有可能出现问题,如果parallel之后的操作并不是原子性的,那么就会导致线程不安全。
// 例如这种情况,每次计算出来的结果都会不同
static Long total = 0L;
LongStream.rangeClosed(1, 300).parallel().forEach(a-> {
total += a;
} );
System.out.println(total);
使用并行流需要注意
- 如果数据量少,那么没必要用并行流
- 自动装箱和拆箱操作会大大降低性能。 Java 8中有原始类型流(IntStream、LongStream、 DoubleStream)来避免这种操作,但凡有可能都应该用这些流
- 有一些操作顺序流本身就比并行流性能好