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秒。大概提升一倍的效率。
网友评论