六问六答理解ForkJoin原理
摘要:ForkJoin线程池是将任务分割为子任务,有可能子任务还是很大,还需要进一步拆解,最终得到足够小的任务。
本文分享自华为云社区《ForkJoin线程池的学习和思考》,作者:breakDraw。
ForkJoin线程池在常规的java书籍里还是提到比较少的,毕竟是java8引入的产物。
首先这里简单解释一下forkJoin的运作原理, 本质上有点像归并计算。
- 他会将提交大任务按照一定规则拆解(fork)成多个小任务
- 当任务小到一定程度时,就会执行计算
- 执行完成时会和其他的小任务进行合并(join), 逐步将所有小结果合成一个大结果。

可以看这个forkJoinTask的实现伪代码,即如果想使用forkJoin并发执行任务,需要自己把任务继承RecursiveTask,作为forkJoin池的submit对象:
public class ForkJoinTask extends RecursiveTask<任务参数> {
public ReckonTask(任务参数) {
}
@Override
protected File compute() {
if(根据任务参数判断任务是否足够小) {
计算,返回
} else {
拆分成子任务1和子任务2
任务1.fork();
任务2.fork();
结果1 = 任务1.join();
结果2 = 任务2.join();
返回结果1+结果2;
}
}
}
然后实际上整个forkjoin的细节非常多,这里我通过给自己提好几个问题,来逐步理解forkJoin的原理:
Q: forkJoin中各个线程是如何获取那些小任务的呢?
A:他是通过工作密取的方式获取。(java并发那本书里提到过工作密取workSteal,原来是用在这了)
- 假设我们给forkJoin设置3个工作线程,那么就会有3个工作队列, 注意,这个队列是双端队列。
- 每当执行任务时,如果不满足小任务的条件,他会fork出2个子任务,并push进自己的工作队列中。
- 每个工作线程不断取自己队头的任务执行。
- 关键点:如果自己队列里没有数据,则会从其他队列的队尾取数据。
Q: fork时具体发生了什么?
A:是一个异步的操作, 就是向当前线程队列中添加这个fork出来任务,能放进去的话就返回,不会等待。
注意,默认fork出的任务是先默认给自己的。 当自己做不完时,才可能被别人取走!

Q: join是什么含义?什么时候做的?
A:见实现forkJoin任务接口时的代码:

可以看到时每次fork完之后, 通过join,来获取子task的结果,获取到之后,再合并计算,返回结果。
Q: join这个阻塞过程是怎么做的?如果把线程挂起,那这个线程岂不是无法工作了?
A:首先,之前fork时,新的子任务已经被放入队列了。
每个子任务都有一个任务状态。
当调用该子任务的join时, 会循环判断他的状态
如果这个子任务状态未完成, 则从自身队列或其他人的队列中取出新的任务执行,因此进入了下一层的exec()操作。
如果发现子任务状态更新为了完成(这个更新动作可能是自己线程完成的,也可能是别的线程完成的,反正这个任务的状态实现了同步和可见), 则将结果返回给上层。
因此join的本质是一个递归的过程, 任务没完成的话,他就取其他任务继续递归往下执行。
更详细的可以看这个链接fork+join过程详细解读
Q: forkJoin存放任务的时候,怎么保证不会出现并发问题?比如同时往队尾插入的话
A:
- n个工作线程是通过数组存放的(即有一个工作线程数组)
- sun.misc.Unsafe操作类直接基于操作系统控制层在硬件层面上进行原子操作,它是ForkJoinPool高效性能的一大保证,类似的编程思路还体现在java.util.concurrent包中相当规模的类功能实现中。

Q: forkJoin应用在哪吗?
A:java8 stream的parallel并发功能就是基于forkJoin做的, parallelStream实现的forkJoin拆解任务和执行任务的接口, 默认用机器所有CPU数量的forkJoin线程池。
如果需要限制线程数量,可以用
new forkJoin(线程数).submit(()->(list.stream().parallel().map()…)); 即可
六问六答理解ForkJoin原理的更多相关文章
- exec 跟 source 差在哪?-- Shell十三问<第六问>
exec 跟 source 差在哪?-- Shell十三问<第六问> 这次先让我们从 CU Shell 版的一个实例贴子来谈起吧: 例中的提问是: cd /etc/aa/bb/cc 可以执 ...
- 拜托!面试请不要再问我Spring Cloud底层原理[z]
[z]https://juejin.im/post/5be13b83f265da6116393fc7 拜托!面试请不要再问我Spring Cloud底层原理 欢迎关注微信公众号:石杉的架构笔记(id: ...
- 《深入理解mybatis原理》 MyBatis的架构设计以及实例分析
作者博客:http://blog.csdn.net/u010349169/article/category/2309433 MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简 ...
- k3 Bos开发百问百答
K/3 BOS开发百问百答 (版本:V1.1) K3产品市场部 目录 一.基础资料篇__ 1 [摘要]bos基础资料的显示问题_ 1 [摘要]单 ...
- 《深入理解mybatis原理3》 Mybatis数据源与连接池
<深入理解mybatis原理> Mybatis数据源与连接池 对于ORM框架而言,数据源的组织是一个非常重要的一部分,这直接影响到框架的性能问题.本文将通过对MyBatis框架的数据源结构 ...
- 《深入理解mybatis原理1》 MyBatis的架构设计以及实例分析
<深入理解mybatis原理> MyBatis的架构设计以及实例分析 MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单.优雅.本文主要讲述MyBatis的架构 ...
- 第九节: 利用RemoteScheduler实现Sheduler的远程控制 第八节: Quartz.Net五大构件之SimpleThreadPool及其四种配置方案 第六节: 六类Calander处理六种不同的时间场景 第五节: Quartz.Net五大构件之Trigger的四大触发类 第三节: Quartz.Net五大构件之Scheduler(创建、封装、基本方法等)和Job(创建、关联
第九节: 利用RemoteScheduler实现Sheduler的远程控制 一. RemoteScheduler远程控制 1. 背景: 在A服务器上部署了一个Scheduler,我们想在B服务器上 ...
- Java 面试题问与答:编译时与运行时
Java 面试题问与答:编译时与运行时 2012/12/17 | 分类: 基础技术, 职业生涯 | 5 条评论 | 标签: RUNTIME, 面试 分享到:58 本文作者: ImportNew - 朱 ...
- OpenGL快问快答
OpenGL快问快答 本文内容主要来自对(http://www.opengl.org/wiki/FAQ)的翻译,随机加入了本人的观点.与原文相比,章节未必完整,含义未必雷同,顺序未必一致.仅供参考. ...
随机推荐
- 用 openresty 编写 lua
""" #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/erro ...
- Jmeter压测学习6---登录参数CSV
前言 我们在压测登录接口的时候,如果只用一个账号去设置并发压测,这样的结果很显然是不合理的,一个用户并发无法模拟真实的情况.如果要压测登录接口,肯定得准备几百,甚至上千的账号去登录,测试的结果才具有可 ...
- 测试用例 setup 和 和 teardown
前言 学过unittest的都知道里面用前置和后置setup呾teardown非常好用,在每次用例开始前呾结束后都去执行一次.当然迓有更高级一点的 setupClass 呾 teardownClass ...
- Kubernetes-Service介绍(一)-基本概念
前言 本篇是Kubernetes第八篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战.Pod篇暂时应该还缺少两篇,等Service和存储相关内容介绍以后,补充剩下的两篇,有状态的Pod会涉及 ...
- jupyter 快捷命令
-- https://www.jb51.net/article/199930.htm#:~:text=Jupyter notebook命令和编辑模式常用快捷键汇总 1 Enter %3A 转入编辑模式 ...
- FastAPI(44)- 操作关系型数据库
ORM FastAPI 可与任何数据库和任何样式的库配合使用并和数据库通信 object-relational mapping 对象关系映射 ORM 具有在代码和数据库表(关系)中的对象之间进行转换( ...
- mybatis 配置问题查找
mybatis配置问题记录 org.apache.ibatis.binding.BindingException: Type interface com.xx.dao.UserDao(自己项目的文件) ...
- 基于Hexo+Github Pages搭建的博客
概念 Github Pages可以被认为是用户编写的.托管在github上的静态网页.使用Github Pages可以为你提供一个免费的服务器,免去了自己搭建服务器和写数据库的麻烦.此外还可以绑定自己 ...
- 极简SpringBoot指南-Chapter00-学习SpringBoot前的基本知识
仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...
- 从零入门 Serverless | 函数计算的开发与配置
导读:在本篇文章中,"基本概念"部分主要对函数计算最核心的概念进行详细介绍,包括服务.函数.触发器.版本.别名以及相关的配置:"开发流程"部分介绍了基于函数计算 ...