【Java并发编程的艺术】Java并发容器和框架:ForkJoin框架

it2023-05-10  80

1.什么是Fork/join框架

用于执行并行任务,是把一个大任务分成若干个小任务执行(fork),最终汇总每个小任务结果后得到大任务结果(join)的框架。

适用于CPU密集型运算,默认会创建与CPU核心数相等的线程池。

2.工作窃取算法

2.1 介绍

工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行。 干完活的线程会从其他线程的双端队列尾部窃取任务来完成,而被窃取的线程则是从双端队列的头部取出任务。

2.2 优点

充分利用线程进行并行计算,减少了线程间的竞争。

2.3 缺点

在某些情况下还是存在竞争,比如双端队列中只有一个任务时。并且该算法会消耗了更多的系统资源,比如创建多个线程和多个双端队列。

3.使用

分割的子任务分别放在双端队列里,然后几个启动线程分别从双端队列里获取任务执行。子任务执行完的结果都统一放在一个队列里,启动一个线程从队列里拿数据,然后合并这些数据。 ①ForkJoinTask:我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制。通常情况下,我们不需要直接继承ForkJoinTask类,只需要继承它的子类,Fork/Join框架提供了以下两个子类。 -RecursiveAction:用于没有返回结果的任务。 -RecursiveTask:用于有返回结果的任务。 ②ForkJoinPool:ForkJoinTask需要通过ForkJoinPool来执行。

使用示例代码如下

import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Future; import java.util.concurrent.RecursiveTask; public class CountTask extends RecursiveTask<Integer> { private static final int THRESHOLD=2; private int start; private int end; public CountTask(int start,int end){ this.start=start; this.end=end; } @Override protected Integer compute() { int sum=0; boolean canCompute=(end-start)<=THRESHOLD; if(canCompute){ for(int i=start;i<=end;i++){ sum+=i; } } else{ int middle=(start+end)/2; CountTask leftTask=new CountTask(start,middle); CountTask rightTask=new CountTask(middle+1,end); leftTask.fork(); rightTask.fork(); int leftResult=leftTask.join(); int rightResult=rightTask.join(); sum=leftResult+rightResult; } return sum; } public static void main(String[] args) { ForkJoinPool pool=new ForkJoinPool(); CountTask task=new CountTask(2,4); Future<Integer> result=pool.submit(task); try{ System.out.println(result.get()); } catch (Exception e){ } } }

输出

最新回复(0)