java8的parallelStream

先看一段代码,分别为串行遍历、并行遍历、并行加锁遍历:

private static List list1 = new ArrayList<>();
private static List list2 = new ArrayList<>();
private static List list3 = new ArrayList<>();
private static Lock lock = new ReentrantLock();

public static void testStrem(){
    int max = 10000;
    long startTime1=System.currentTimeMillis();   //获取开始时间
    //串行遍历
    IntStream.range(0,max).forEach(i->{
        try{
            list1.add(i);
        } finally {
        }
    });
    long endTime1=System.currentTimeMillis();

    long startTime2=System.currentTimeMillis();   
    //并行执行
    IntStream.range(0,max).parallel().forEach(i->{
        try{
            list2.add(i);
        } finally {
        }
    });
    long endTime2=System.currentTimeMillis();


    long startTime3=System.currentTimeMillis();   
    //加锁并行执行
    IntStream.range(0,max).parallel().forEach(i->{
        lock.lock();
        try{
            list3.add(i);
        } finally {
            lock.unlock();
        }
    });
    long endTime3=System.currentTimeMillis();

    System.out.println("串行执行的大小:" + list1.size()+" 程序运行时间: "+(endTime1-startTime1)+"ms");
    System.out.println("并行执行的大小:" + list2.size()+" 程序运行时间: "+(endTime2-startTime2)+"ms");
    System.out.println("加锁并行执行的大小:" + list3.size()+" 程序运行时间: "+(endTime3-startTime3)+"ms");
}

执行结果:

串行执行的大小:10000 程序运行时间: 71ms
并行执行的大小:9567 程序运行时间: 10ms
加锁并行执行的大小:10000 程序运行时间: 5ms
---------------------------------------------------
串行执行的大小:100000 程序运行时间: 75ms
并行执行的大小:74661 程序运行时间: 13ms
加锁并行执行的大小:100000 程序运行时间: 18ms

从执行结果来看,parallelStream并非线程安全,所以配合锁既可以保证线程安全,还可以提高效率。

parallelStream就是其中一个非常使用的特性。我总结了几个好处:

  • 代码优雅,可以使用lambda表达式,原本几句代码现在一句可以搞定
  • 运用多核特性(forkAndJoin)并行处理,大幅提高效率。

parallelStream使用时需要注意的点:

  • parallelStream 只是做到别浪费cpu,假如本身电脑cpu的负载很大,那还到处用parallel,那并不能起到作用
  • 不要在多线程中使用parallelStream,原因同上类似,大家都抢着cpu是没有提升效果,反而还会加大线程切换开销
  • 会带来不确定性,请确保每条处理无状态且没有关联
  • 考虑nq模型:n可用的数据量,q针对每个数据元素执行的计算量乘积 N*Q 越大,就越有可能获得并行提速。N x Q > 10000 就会获得有效提升


你可能感兴趣的:(java)