Fork/Join框架

Fork/Join 以递归方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果。

这个过程其实就是分治算法的并行版本,图解如下:

如何使用

我们要使用 ForkJoin 框架,必须先创建一个 ForkJoinTask。它提供在任务中执行 fork() 和 join() 操作的机制,通常情况下我们不需要直接继承 ForkJoinTask 类,而只需要继承它的子类,Fork/Join 框架提供了以下两个子类:

  • RecursiveAction:用于没有返回结果的任务。
  • RecursiveTask :用于有返回结果的任务。

而ForkJoinTask 需要通过 ForkJoinPool 来执行,任务分割出的子任务会添加到当前工作线程所维护的双端队列中,进入队列的头部。

下面使用forkJoin来计算一个Integer List之和:


import com.google.common.collect.Lists;
import com.sun.istack.internal.NotNull; import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;
import java.util.stream.IntStream; public class SumTask extends RecursiveTask<Long> { private static final int SPLIT_NUM = 10000;
@NotNull
private List<Integer> numberList; public SumTask(List<Integer> numberList) {
this.numberList = numberList;
} @Override
protected Long compute() {
// 不需要进行任务拆分
if (numberList.size() <= SPLIT_NUM) {
return numberList.stream().mapToLong(Integer::intValue).sum();
}
// 进行任务拆分
List<List<Integer>> splitNumberList = Lists.partition(numberList, numberList.size() / 2);
List<SumTask> sumTasks = splitNumberList.stream().map(SumTask::new).collect(Collectors.toList());
// 执行子任务,继续拆分
invokeAll(sumTasks);
// 合并结果
return sumTasks.stream().mapToLong(SumTask::join).sum();
} public static void main(String[] args) {
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
List<Integer> numberList = IntStream.rangeClosed(1, 100000).mapToObj(Integer::new).collect(Collectors.toList());
SumTask sumTask = new SumTask(numberList);
Long sum = forkJoinPool.invoke(sumTask);
System.out.println("1 ~ 100000 sum result is: " + sum);
}
}

上述代码的执行过程为,先将List 分为两个子List, 并发执行两个子List 的计算。然后再将子List 拆分为更小的List,依此往复,直至List无法再拆分时,计算其Sum,最后合并结果。

ForkJoinTask 与一般的任务的主要区别在于它需要实现 compute 方法,在这个方法里,首先需要判断任务是否足够小,如果足够小就直接执行任务。如果不足够小,就必须分割成两个子任务,每个子任务在调用 fork 方法时,又会进入 compute 方法,形成递归调用,直到任务子任务不可再分。使用 join 方法会等待子任务执行完并得到其结果。

异常捕获

我们没办法在主线程中捕获ForkJoinTask 执行过程中抛出的异常。所以ForkJoinTask 提供了方法来检测Task 执行情况, 并提供了获取异常的方法。

        // 检查Task 执行情况
sumTask.isCancelled();
sumTask.isCompletedNormally();
sumTask.isCompletedAbnormally(); // 获取异常信息
sumTask.getException();

实现原理

参考 https://segmentfault.com/a/1190000016781127

Java Fork/Join的更多相关文章

  1. Java Fork/Join 框架

    简介 从JDK1.7开始,Java提供Fork/Join框架用于并行执行任务,它的思想就是讲一个大任务分割成若干小任务,最终汇总每个小任务的结果得到这个大任务的结果. 这种思想和MapReduce很像 ...

  2. Fork/Join 框架-设计与实现(翻译自论文《A Java Fork/Join Framework》原作者 Doug Lea)

    作者简介 Dong Lea任职于纽约州立大学奥斯威戈分校(State University of New York at Oswego),他发布了第一个广泛使用的java collections框架实 ...

  3. java Fork/Join框架

    应用程序并行计算遇到的问题 当硬件处理能力不能按摩尔定律垂直发展的时候,选择了水平发展.多核处理器已广泛应用,未来处理器的核心数将进一步发布,甚至达到上百上千的数量.而现在很多的应用程序在运行在多核心 ...

  4. JAVA FORK JOIN EXAMPLE--转

    http://www.javacreed.com/java-fork-join-example/ Java 7 introduced a new type of ExecutorService (Ja ...

  5. java fork/join简单实践

    我们知道,java8中有并行流,而并行流在后台的实现是通过fork/join池来完成的,例如: List<Integer> a = buildList(); List<Integer ...

  6. Java fork join ForkJoinPool 用法例子

    本例是把一个大的数组求和的计算的大任务分解到在小范围内求和的小任务,然后把这些小任务之和加起来就是所求之结果. 技术:JDK8.0, Javafork-join模式下的RecursiveTask技术, ...

  7. Java并发——Fork/Join框架

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/4631466. ...

  8. 《java.util.concurrent 包源码阅读》22 Fork/Join框架的初体验

    JDK7引入了Fork/Join框架,所谓Fork/Join框架,个人解释:Fork分解任务成独立的子任务,用多线程去执行这些子任务,Join合并子任务的结果.这样就能使用多线程的方式来执行一个任务. ...

  9. 《java.util.concurrent 包源码阅读》24 Fork/Join框架之Work-Stealing

    仔细看了Doug Lea的那篇文章:A Java Fork/Join Framework 中关于Work-Stealing的部分,下面列出该算法的要点(基本是原文的翻译): 1. 每个Worker线程 ...

随机推荐

  1. 关于Excel中表格转Markdown格式的技巧

    背景介绍 Excel文件转Markdown格式的Table是经常会遇到的场景. Visual Studio Code插件 - Excel to Markdown table Excel to Mark ...

  2. 视频云峰会|“科技 X 艺术” 的颗粒度体验是什么?

    科技日新月异,交互艺术新门类也随之蓬勃,当代艺术创作者不断凭借其想象力和跨学科能力,致力科技与艺术的融合创作. 7 月 10 日,在北京,2021 阿里云视频云全景创新峰会暨全球视频云创新挑战赛决赛颁 ...

  3. linux sort uniq命令详解

    sort 功能说明:将文本文件内容加以排序,sort可针对文本文件的内容,以行为单位来排序. sort [-bcdfimMnr][-o<输出文件>][-t<分隔字符>][+&l ...

  4. 关于中文版的manpages

    可以从下面下载对应的包: https://code.google.com/p/manpages-zh/ https://github.com/lidaobing/manpages-zh 目前只有一部分 ...

  5. XCTF(MISC) 坚持60s

    题目描述:菜狗发现最近菜猫不爱理他,反而迷上了菜鸡 下载附件,发现是一个游戏,同时要玩到60s才能得到flag(可恶,完全玩不到60s,被疯狂嘲讽) ------------------------- ...

  6. ASP.NET 检测当前计算机及登录用户名

    TextBox1.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

  7. 手把手0基础Centos下安装与部署paddleOcr 教程

    !!!以下内容为作者原创,首发于个人博客园&掘金平台.未经原作者同意与许可,任何人.任何组织不得以任何形式转载.原创不易,如果对您的问题提供了些许帮助,希望得到您的点赞支持. 0.paddle ...

  8. [010] - JavaSE面试题(十):集合之Map

    第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [010] - JavaSE面试题(十):集合之Map 第1问:HashMap和HashTable ...

  9. [刘阳Java]_纯CSS代码实现内容过滤效果

    继续我们技术专题课,我们今天给大家带来的是一个比较酷炫的"纯CSS代码实现内容过滤效果",没有加入任何JS的效果.全部都是应用CSS3的新增选择器来实现的.先看效果截图 实现思路 ...

  10. 汉诺塔Python

    刚开始看python实现汉诺塔,自己想了很久才想明白,在这里记录一下,希望以后忘记能够立马记起. n=1时,可以直接a->c n=2时,可以借助b然后将a->c n=3时,可以将最上面的那 ...