
文章插图
ForkJoinPool 框架中涉及的主要类如下所示 。
1.ForkJoinPool类实现了ForkJoin框架中的线程池,由类图可以看出,ForkJoinPool类实现了线程池的Executor接口 。
我们也可以从下图中看出ForkJoinPool的类图关系 。

文章插图
其中,可以使用Executors.newWorkStealPool()方法创建ForkJoinPool 。
ForkJoinPool中提供了如下提交任务的方法 。public void execute(ForkJoinTask<?> task)public void execute(Runnable task)public <T> T invoke(ForkJoinTask<T> task)public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task)public <T> ForkJoinTask<T> submit(Callable<T> task)public <T> ForkJoinTask<T> submit(Runnable task, T result)public ForkJoinTask<?> submit(Runnable task)2.ForkJoinWorkerThread类实现ForkJoin框架中的线程 。
3.ForkJoinTask<V>类ForkJoinTask封装了数据及其相应的计算,并且支持细粒度的数据并行 。ForkJoinTask比线程要轻量,ForkJoinPool中少量工作线程能够运行大量的ForkJoinTask 。
ForkJoinTask类中主要包括两个方法fork()和join(),分别实现任务的分拆与合并 。
fork()方法类似于Thread.start(),但是它并不立即执行任务,而是将任务放入工作队列中 。跟Thread.join()方法不同,ForkJoinTask的join()方法并不简单的阻塞线程,而是利用工作线程运行其他任务,当一个工作线程中调用join(),它将处理其他任务,直到注意到目标子任务已经完成 。
我们可以使用下图来表示这个过程 。

文章插图
ForkJoinTask有3个子类:

文章插图
- RecursiveAction:无返回值的任务 。
- RecursiveTask:有返回值的任务 。
- CountedCompleter:完成任务后将触发其他任务 。
5.RecursiveAction类无返回结果的ForkJoinTask实现Runnable 。
6.CountedCompleter<T> 类在任务完成执行后会触发执行一个自定义的钩子函数 。
ForkJoin示例程序package io.binghe.concurrency.example.aqs;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.ForkJoinPool;import java.util.concurrent.Future;import java.util.concurrent.RecursiveTask;@Slf4jpublic class ForkJoinTaskExample extends RecursiveTask<Integer> { public static final int threshold = 2; private int start; private int end; public ForkJoinTaskExample(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; ForkJoinTaskExample leftTask = new ForkJoinTaskExample(start, middle); ForkJoinTaskExample rightTask = new ForkJoinTaskExample(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 forkjoinPool = new ForkJoinPool(); //生成一个计算任务,计算1+2+3+4 ForkJoinTaskExample task = new ForkJoinTaskExample(1, 100); //执行一个任务 Future<Integer> result = forkjoinPool.submit(task); try { log.info("result:{}", result.get()); } catch (Exception e) { log.error("exception", e); } }}
经验总结扩展阅读
- 送花给女朋友写点什么好呢
- 2023年9月24日回娘家好不好 2023年9月24日是回娘家的黄道吉日吗
- 送大学生女生什么礼物好
- 2023年农历八月初十宜打猎吗 2023年9月24日是打猎吉日吗
- 生孩子送什么礼物合适
- 给父母买什么礼物最实用
- 见女方父母送什么礼物好
- 送爸爸什么礼物好
- 2023年农历八月初十宜认干儿子吗 2023年9月24日是认干儿子吉日吗
- 孕妇生日送什么礼物合适