Java中不同的并发实现的性能比较

来源:互联网 发布:经典小说推荐 知乎 编辑:程序博客网 时间:2024/05/21 11:18

看的一篇文章,名为:《Java中不同的并发实现的性能比较》。这篇文件比较了ExecutorService vs. Fork/Join框架 vs. 并行流之间的性能。结论是:

在“CPU/IO密集”型工作中,在使用CPU核数不同时,每种框架的表现也不相同。

具体内容大家可以自己看看文章。
 

但在这篇文章中,有一个细节也需要注意一下,就是关于ForkJoinPool里的commonPool
在使用ForkJoinTask并行流时,有一些情况下会默认使用ForkJoinPool里的commonPoolcommonPool的默认使用线程数,为CPU核的大小。但有些时候(比如:IO密集操作时)扩大这个线程数,能提程序高性能。
如何修改commonPool的线程数大小呢?
这时候,可以使用-Djava.util.concurrent.ForkJoinPool.common.parallelism=16参数,在启动JVM时修改这个线程数大小。
有时候一个程序中要启动多个这种并行处理,如果这些处理都使用commonPool的话,可能会造成有的处理会一直执行不完(因为ForkJoinPool的Work Thread的队列在处理Task时,是LIFO的原因),所以我们可能会需要创建一个独立ForkJoinPool。如果是ForkJoinTask的话,大家可能都会。但如果对一个并行流使用一个独立的ForkJoinPool的话,应该如何做呢?方法如下:

ForkJoinPool forkJoinPool = new ForkJoinPool(2);  ...  forkJoinPool.submit(() ->      range(1, 1_000_000).parallel().filter(PrimesPrint::isPrime)          .collect(toList())  ).get();  

这个方法还能同时解决两个问题:
1. 提交计算的线程,会被当做一个worker用作执行计算处理。这样的话,就把这个提交线程和pool里的线程混合使用了,问题是提交线程pool里的线程的生命周期是不一样的,可能会产生问题。这篇文章就说了几个可能会产生的问题。独立使用ForkJoinPool,我们就可以保证被使用的线程都是pool里的线程。
 
2. 另一个问题是,使用独立的ForkJoinPool,可以设置中断时间。这样话,如果处理超过了我们预订的时间,就可以使它自动中断。


最后,大家有空可以看看可能会产生问题的这篇文章,这篇文章除了说明了可能会产生问题,还对ForkJoinPool框架做了批评,值得一看。(里面的英文有很多不认识,或不常看到的字,一个意思可能会用很多同义词来表达。。。)
 

0 0
原创粉丝点击