一、 工作原理:
parallel stream内部采用的是fork/join 框架,将一个大任务划分成几个小任务在不同的线程上执行,之后再将结果归并;
所有fork/join 的任务都是使用的一个公共的静态池,线程数量默认为内核的数量;故如果处理I/O密集型任务,可能会存在某线程被阻塞而不能被重新使用,某时刻可能存在线程用光的情况;
由于其机制是“工作窃取i机制”,则可能会存在一个线程做完了自己任务队列里的任务,然后去“窃取”其他队列里的任务,当这个队列里只有一个任务,两个线程可能会争抢一个任务而导致阻塞
1.“工作窃取算法”:某个线程执行完自己的队列里的任务时,会从其他队列里窃取任务来执行
2. 框架局限性:
- 存在竞争:双端队列里只有一个任务时
二、 应用
1. java8 中的parallel stream
因为最近项目中一个计算量很大的任务中使用了parallel stream去并行地计算机器学习模型,最近找系统耗时瓶颈,发现这一块可能存在问题,于是打算深入研究下
三、性能测试
使用JMH性能测试框架分别对使用单线程串行计算模型和使用parallel stream并行计算的函数进行了测试
测试环境:本地测试机器cpu核数:4
分别设置fork/join 池大小1、4、8 : -Djava.util.concurrent.ForkJoinPool.common.parallelism:4
测试结果:线程数设置为1、4、8的时候parallel stream性能差别不大; 并行计算确实比串行计算性能高几倍
Benchmark Mode Cnt Score Error Units
ParallelStreamBenchmark.parallelBench1 avgt 50 0.158 ± 0.013 ms/op
ParallelStreamBenchmark.simpleBench avgt 50 0.335 ± 0.007 ms/op
参考文档:
基准性能测试:Fork/Join Framework vs. Parallel Streams vs. ExecutorService
Java8中 Parallel Streams 的陷阱 [译]