什么是ForkJoin?看这一篇就能掌握!

在JDK中,提供了这样一种功能:它能够将复杂的逻辑拆分成一个个简单的逻辑来并行执行,待每个并行执行的逻辑执行完成后,再将各个结果进行汇总,得出最终的结果数据 。有点像Hadoop中的MapReduce 。
ForkJoin是由JDK1.7之后提供的多线程并发处理框架 。ForkJoin框架的基本思想是分而治之 。什么是分而治之?分而治之就是将一个复杂的计算,按照设定的阈值分解成多个计算,然后将各个计算结果进行汇总 。相应的,ForkJoin将复杂的计算当做一个任务,而分解的多个计算则是当做一个个子任务来并行执行 。
Java并发编程的发展对于Java语言来说,生来就支持多线程并发编程,在并发编程领域也是在不断发展的 。Java在其发展过程中对并发编程的支持越来越完善也正好印证了这一点 。

  • Java 1 支持thread,synchronized 。
  • Java 5 引入了 thread pools,blocking queues, concurrent collections,locks, condition queues 。
  • Java 7 加入了fork-join库 。
  • Java 8 加入了 parallel streams 。
并发与并行并发和并行在本质上还是有所区别的 。
并发并发指的是在同一时刻,只有一个线程能够获取到CPU执行任务,而多个线程被快速的轮换执行,这就使得在宏观上具有多个线程同时执行的效果,并发不是真正的同时执行,并发可以使用下图表示 。
什么是ForkJoin?看这一篇就能掌握!

文章插图
并行并行指的是无论何时,多个线程都是在多个CPU核心上同时执行的,是真正的同时执行 。
什么是ForkJoin?看这一篇就能掌握!

文章插图
分治法基本思想把一个规模大的问题划分为规模较小的子问题,然后分而治之,最后合并子问题的解得到原问题的解 。
步骤①分割原问题;
②求解子问题;
③合并子问题的解为原问题的解 。
我们可以使用如下伪代码来表示这个步骤 。
if(任务很小){ 直接计算得到结果}else{ 分拆成N个子任务 调用子任务的fork()进行计算 调用子任务的join()合并计算结果}在分治法中,子问题一般是相互独立的,因此,经常通过递归调用算法来求解子问题 。
典型应用
  • 二分搜索
  • 大整数乘法
  • Strassen矩阵乘法
  • 棋盘覆盖
  • 合并排序
  • 快速排序
  • 线性时间选择
  • 汉诺塔
ForkJoin并行处理框架ForkJoin框架概述Java 1.7 引入了一种新的并发框架—— Fork/Join Framework,主要用于实现“分而治之”的算法,特别是分治之后递归调用的函数 。
ForkJoin框架的本质是一个用于并行执行任务的框架,能够把一个大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务的计算结果 。在Java中,ForkJoin框架与ThreadPool共存,并不是要替换ThreadPool
其实,在Java 8中引入的并行流计算,内部就是采用的ForkJoinPool来实现的 。例如,下面使用并行流实现打印数组元组的程序 。
public class SumArray { public static void main(String[] args){ List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9); numberList.parallelStream().forEach(System.out::println); }}这段代码的背后就使用到了ForkJoinPool 。
说到这里,可能有读者会问:可以使用线程池的ThreadPoolExecutor来实现啊?为什么要使用ForkJoinPool啊?ForkJoinPool是个什么鬼啊?! 接下来,我们就来回答这个问题 。
ForkJoin框架原理ForkJoin框架是从jdk1.7中引入的新特性,它同ThreadPoolExecutor一样,也实现了Executor和ExecutorService接口 。它使用了一个无限队列来保存需要执行的任务,而线程的数量则是通过构造函数传入,如果没有向构造函数中传入指定的线程数量,那么当前计算机可用的CPU数量会被设置为线程数量作为默认值 。

经验总结扩展阅读