温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何理解Java 并发编程中的ForkJoin框架

发布时间:2021-11-24 12:51:50 来源:亿速云 阅读:154 作者:柒染 栏目:开发技术

如何理解Java 并发编程中的ForkJoin框架,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

1、什么是ForkJoin框架

ForkJoin框架是java的JUC包里提供的,用于处理一些比较繁重的任务,会将这个大任务分为多个小任务,多个小任务处理完成后会将结果汇总给Result,体现的是一种“分而治之”的思想。第一步,拆分fork任务,将大任务分为多个小任务;第二步,归并join,会将小任务的处理结果进行归并为一个结果。

如何理解Java 并发编程中的ForkJoin框架

2、ForkJoinTask

ForkJoinTask是ForkJoin框架的提供的任务API,ForkJoinTask是一个抽象类,有两个主要的实现类,RecursiveTask和RecursiveAction,其中RecursiveTask和RecursiveAction的主要区别是,RecursiveAction没有返回值,而RecursiveTask是有返回值的

如何理解Java 并发编程中的ForkJoin框架

3、ForkJoinPool

ForkJoinPool类是forkjoin框架的线程池实现,基于ExecutorService接口。这个线程池是jdk1.7才加入的,用于管理线程,执行forkjoin的任务。对于线程池的使用,我们使用ThreadPoolExecutor比较多,可以在idea里看一下uml类图,可以看出ForkJoinPool和ThreadPoolExecutor实现差不多的。

如何理解Java 并发编程中的ForkJoin框架

ForkJoinPool() ForkJoinPool(int parallelism) ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory,  UncaughtExceptionHandler handler, boolean asyncMode)

几个重要的参数:

  • parallelism:并行度,并行执行线程,可用指定,也可以不指定,不指定的情况,是根据cpu核数创建可用的线程

  • ForkJoinWorkerThreadFactory:创建线程的工厂实现

  • UncaughtExceptionHandler :因为未知异常中断的回调处理

  • asyncMode:是否异步,默认情况是false

使用时候,可以直接创建ForkJoinPool,可以不传参,不传参的情况,默认指定的线程并行数为Runtime.getRunTime().availableProcessors();,表示根据cpu核数创建可用线程数

ForkJoinPool forkJoinPool = new ForkJoinPool(); ArraySortTask task = new ArraySortTask(array , 0 , size); forkJoinPool.submit(task); task.get();

也是可用传参,对并行度进行指定的public ForkJoinPool(int parallelism), parallelism并行度,并行执行几个线程

将forkjoin任务加入到FrokJoinPool线程池有几种方式

  • execute():调用其 fork 方法在多个线程之间拆分工作。

  • invoke():在ForkJoinPool线程池上调用invoke方法

  • submit():返回一个Future对象,Future可以进行监控,任务完成后返回结果

4、打印斐波那契数列

ForkJoin框架可以用于一些递归遍历的场景,对于斐波那契数列,你可以比较熟悉,因为在面试中有时候经常问到,斐波那契数列的特点就是最后一项的结果等于前面两项的和

package com.example.concurrent.forkjoin; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.RecursiveTask; /**  * <pre>  *      斐波那契数列  * </pre>  * <p>  * <pre>  * @author nicky.ma  * 修改记录  *    修改后版本:     修改人:  修改日期: 2021/10/12 16:22  修改内容:  * </pre>  */ public class Fibonacci extends RecursiveTask<Integer>{     private int n;     public Fibonacci(int n) {         this.n = n;     }     @Override     protected Integer compute() {         if (n <= 1)             return n;         Fibonacci f1 = new Fibonacci(n - 1);         f1.fork();         Fibonacci f2 = new Fibonacci(n - 2);         f2.fork();         return f1.join() + f2.join();     }     public static void main(String[] args) throws ExecutionException, InterruptedException {         ForkJoinPool pool = new ForkJoinPool();         for (int i = 0; i< 10; i++) {             ForkJoinTask task = pool.submit(new Fibonacci(i));             System.out.println(task.get());         }     } }

5、ForkJoin归并排序

面试题:快速实现对一个长度百万的数组的排序

难点:可以使用归并排序,多线程如何组织实现归并排序

package com.example.concurrent.forkjoin; import java.util.Arrays; import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveAction; /**  * <pre>  *      大数组排序  * </pre>  * <p>  * <pre>  * @author mazq  * 修改记录  *    修改后版本:     修改人:  修改日期: 2021/10/12 17:04  修改内容:  * </pre>  */ public class ArraySortTask extends RecursiveAction{     final long[] array; final int lo, hi;     ArraySortTask(long[] array, int lo, int hi) {         this.array = array; this.lo = lo; this.hi = hi;     }     ArraySortTask(long[] array) { this(array, 0, array.length); }     @Override     protected void compute() {         if (hi - lo < THRESHOLD)             // 少于阀值,使用Arrays.sort 快排             sortSequentially(lo, hi);         else {             /* 归并排序 */             // 取中间值             int mid = (lo + hi) >>> 1;             // 拆分任务             invokeAll(new ArraySortTask(array, lo, mid),                     new ArraySortTask(array, mid, hi));             // 归并结果             merge(lo, mid, hi);         }     }     // implementation details follow:     static final int THRESHOLD = 1000;     void sortSequentially(int lo, int hi) {         Arrays.sort(array, lo, hi);     }     void merge(int lo, int mid, int hi) {         long[] buf = Arrays.copyOfRange(array, lo, mid);         for (int i = 0, j = lo, k = mid; i < buf.length; j++)             array[j] = (k == hi || buf[i] < array[k]) ?                     buf[i++] : array[k++];     }     public static void main(String[] args) throws ExecutionException, InterruptedException {         int size = 10_000;         long[] array = new long[size];         Random random = new Random();         for (int i = 0; i< size; i++) {             array[i] = random.nextInt();         }         ForkJoinPool forkJoinPool = new ForkJoinPool();         ArraySortTask task = new ArraySortTask(array , 0 , size);         forkJoinPool.submit(task);         task.get();         for (long a : array) {             System.out.println(a);         }     } }

关于如何理解Java 并发编程中的ForkJoin框架问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI