深入理解 ForkJoinPool:入门、使用、原理

本文深入探讨了ForkJoinPool的设计初衷和使用场景,通过Fibonacci数列的例子展示了如何使用ForkJoinPool进行并行计算。ForkJoinPool适用于处理有父子任务依赖的并行计算问题,如快速排序、二分查找等。对比ThreadPoolExecutor,ForkJoinPool提供了更便捷的子任务结果获取。文章还介绍了ForkJoinPool的工作窃取算法,确保了任务的高效执行。通过源码分析,揭示了ForkJoinPool如何实现任务的分治和合并。
摘要由CSDN通过智能技术生成

本文将从一个简单的例子出发,与大家解释为啥要有 ForkJoinPool 的存在。接着向大家介绍 ForkJoinPool 的基本信息及使用,最后讲解 ForkJoinPool 的基本原理。 诞生原因 对于线程池来说,我们经常使用的是 ThreadPoolExecutor,可以用来提升任务处理效率。一般情况下,我们使用 ThreadPoolExecutor 的时候,各个任务之间都是没有联系的。但在某些特殊情况下,我们处理的任务之间是有联系的,例如经典的 Fibonacci 算法就是其中一种情况。 对于 Fibonacci 数列来说,我们知道 F (N) = F (N-1) + F (N-2)。当前数值的结果,都依赖后面几个数值的结果。这时候如果用 ThreadPoolExecutor 貌似就无法解决问题了。虽然我们可以单线程的递归算法,则其计算速度较慢,并且无法进行并行计算,无法发挥 CPU 多核的优势。 ForkJoinPool 就是设计用来解决父子任务有依赖的并行计算问题的。 类似于快速排序、二分查找、集合运算等有父子依赖的并行计算问题,都可以用 ForkJoinPool 来解决。对于 Fibonacci 数列问题,如果用 ForkJoinPool 来实现,其实现代码为: @Slf4j public class ForkJoinDemo { // 1. 运行入口 public static void main(String[] args) { int n = 20; // 为了追踪子线程名称,需要重写 ForkJoinWorkerThreadFactory 的方法 final ForkJoinPool.ForkJoinWorkerThreadFactory factory = pool -> { final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); worker.setName("my-thread" + worker.getPoolIndex()); return worker; }; //创建分治任务线程池,可以追踪到线程名称 ForkJoinPool forkJoinPool = new ForkJoinPool(4, factory, null, false); // 快速创建 ForkJoinPool 方法 // ForkJoinPool forkJoinPool = new ForkJoinPool(4); //创建分治任务 Fibonacci fibonacci = new Fibonacci(n); //调用 invoke 方法启动分治任务 Integer result = forkJoinPool.invoke(fibonacci); log.info("Fibonacci {} 的结果是 {}", n, result); } } // 2. 定义拆分任务,写好拆分逻辑 @Slf4j class Fibonacci extends RecursiveTask<Integer> { final int n; Fibonacci(int n) { this.n = n; } @Override public Integer compute() { //和递归类似,定义可计算的最小单元 if (n <= 1) { return n; } // 想查看子线程名称输出的可以打开下面注释 //log.info(Thread.currentThread().getName()); Fibonacci f1 = new Fibonacci(n - 1); // 拆分成子任务 f1.fork(); Fibonacci f2 = new Fibonacci(n - 2); // f1.join 等待子任务执行结果 return f2.compute() + f1.join(); } } 如上面代码所示,我们定义了一个 Fibonacci 类,继承了 RecursiveTask 抽象类。在 Fibonacci 类中,我们定义了拆分逻辑,并调用了 join () 等待子线程执行结果。运行程序,我们会得到如下的结果: 17:29:10.336 [main] INFO tech.shuyi.javaco

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值