JAVA 8 forkjoin实际体验

JAVA8 函数编程

-都说java8 新的函数式编程特别是并行流式编程,但是并行流的性能并不一定就好

        long starttime1=System.currentTimeMillis();
        //cur,bank,eat均为list 
        cul.parallelStream()
                .forEach(tar->{
                    if(bank.parallelStream().
                            filter(poi->dwithin(poi.getLocation(),tar.getLocation(),500))
                            .collect(Collectors.toList()).size()>5 &&
                    eat.parallelStream().
                            filter(poi->dwithin(poi.getLocation(),tar.getLocation(),500))
                            .collect(Collectors.toList()).size()>5
                            )
                        res.add(tar);
                        }

        );
        System.out.println("并行计算耗时:"+String.valueOf(System.currentTimeMillis()-starttime1));
        System.out.println(res.size());
        System.out.println(res.get(0).getName());
        res.clear();
        long starttime=System.currentTimeMillis();
        for(Pois tar:cul){
            List ttmmpp1=new ArrayList();
            List ttmmpp2=new ArrayList();
            for(Pois poi:bank){
                if(dwithin(poi.getLocation(),tar.getLocation(),500))
                    ttmmpp1.add(poi);

            }
            for(Pois poi:eat){
                if(dwithin(poi.getLocation(),tar.getLocation(),500))
                    ttmmpp2.add(poi);

            }
            if(ttmmpp1.size()>5&&ttmmpp2.size()>5)
              res.add(tar);
        }
        System.out.println("顺序执行耗时:"+String.valueOf(System.currentTimeMillis()-starttime));
        System.out.println(res.size());
        System.out.println(res.get(0).getName());



private static boolean dwithin(String A,String B,int radius) {
        try {
            Point a = (Point) reader.read("POINT(" + A.replace(",", " ") + ")");
            Point b = (Point) reader.read("POINT(" + B.replace(",", " ") + ")");
            return a.within(b.buffer(radius));
        }catch(Exception e) {

        }
        return false;
    }

没有很复杂的深层循环,两层。结果可能让人有些失望。
将并行流改成顺序流,时间也少了50ms,这真的是让人有点迷啊。


并行和顺序执行对比测试

原因分析

首先我们看看并行流用了多少线程
System.out.println("ForkJoinPool.getCommonPoolParallelism() : " + ForkJoinPool.getCommonPoolParallelism());
输出:一个线程。
咦,这。。。那设置高一点看看。

 System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + 8);
 System.out.println("ForkJoinPool.getCommonPoolParallelism() : " + ForkJoinPool.getCommonPoolParallelism());

设置无效,参照如下博客修改了一番。
在run-edit configurations中设置JVM参数
-Djava.util.concurrent.ForkJoinPool.common.parallelism=64
其实这样在CPU核心数量达不到的情况下确实提升水平有限。
ps:https://blog.csdn.net/blueskybluesoul/article/details/82817007
按照这个教程修改后,再次测试

修改后如下

final Long starttime2=System.currentTimeMillis();
        ForkJoinPool myPool = new ForkJoinPool(8);
        myPool.submit(() ->cul.parallelStream()
                .forEach(tar->{
                            //System.out.println(tar.getName());
                            if(bank.stream().
                                    filter(poi->dwithin(poi.getLocation(),tar.getLocation(),300))
                                    .collect(Collectors.toList()).size()>5 &&
                                    eat.stream().
                                            filter(poi->dwithin(poi.getLocation(),tar.getLocation(),300))
                                            .collect(Collectors.toList()).size()>5
                                    )res.add(tar);
                        }

                )
        ).get();
        myPool.awaitTermination(3, TimeUnit.SECONDS);
        myPool.shutdown();

修改结果

  • 使用forkjoin指定线程数量,尽管CPU数量有限,依然获得提升。

  • 多次测试,平均顺序流耗时约34秒,并行流耗时约16秒。大概提升一倍的效率。

你可能感兴趣的:(JAVA 8 forkjoin实际体验)