ForkJoinPool
fork():开启一个新线程(或是重用线程池内的空闲线程),将任务交给该线程处理。join():等待该任务的处理线程处理完毕,获得返回值。

ForkJoinPool 的每个工作线程都维护着一个工作队列(WorkQueue),这是一个双端队列(Deque),里面存放的对象是任务(ForkJoinTask)。
每个工作线程在运行中产生新的任务(通常是因为调用了 fork())时,会放入工作队列的队尾,并且工作线程在处理自己的工作队列时,使用的是 LIFO 方式,也就是说每次从队尾取出任务来执行。
每个工作线程在处理自己的工作队列同时,会尝试窃取一个任务(或是来自于刚刚提交到 pool 的任务,或是来自于其他工作线程的工作队列),窃取的任务位于其他线程的工作队列的队首,也就是说工作线程在窃取其他工作线程的任务时,使用的是 FIFO 方式。
在遇到 join() 时,如果需要 join 的任务尚未完成,则会先处理其他任务,并等待其完成。
在既没有自己的任务,也没有可以窃取的任务时,进入休眠。
fork
fork() 做的工作只有一件事,既是把任务推入当前工作线程的工作队列里。可以参看以下的源代码:

join
join() 的工作则复杂得多,也是 join() 可以使得线程免于被阻塞的原因——不像同名的 Thread.join()。
1.检查调用 join() 的线程是否是 ForkJoinThread 线程。如果不是(例如 main 线程),则阻塞当前线程,等待任务完成。如果是,则不阻塞。
2.查看任务的完成状态,如果已经完成,直接返回结果。
3.如果任务尚未完成,但处于自己的工作队列内,则完成它。
4.如果任务已经被其他的工作线程偷走,则窃取这个小偷的工作队列内的任务(以 FIFO 方式),执行,以期帮助它早日完成欲 join 的任务。
5.如果偷走任务的小偷也已经把自己的任务全部做完,正在等待需要 join 的任务时,则找到小偷的小偷,帮助它完成它的任务。
6.递归地执行第5步。

以上就是 fork() 和 join() 的原理,这可以解释 ForkJoinPool 在递归过程中的执行逻辑,但还有一个问题
最初的任务是 push 到哪个线程的工作队列里的?
这就涉及到 submit() 函数的实现方法了
其实除了前面介绍过的每个工作线程自己拥有的工作队列以外,ForkJoinPool 自身也拥有工作队列,这些工作队列的作用是用来接收由外部线程(非 ForkJoinThread 线程)提交过来的任务,而这些工作队列被称为 submitting queue 。
submit() 和 fork() 其实没有本质区别,只是提交对象变成了 submitting queue 而已(还有一些同步,初始化的操作)。submitting queue 和其他 work queue 一样,是工作线程”窃取“的对象,因此当其中的任务被一个工作线程成功窃取时,就意味着提交的任务真正开始进入执行阶段。
ForkJoinPool的更多相关文章
- 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal
什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...
- 【转】线程及同步的性能 - 线程池 / ThreadPoolExecutors / ForkJoinPool
线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自 ...
- ForkJoinPool 源码
ForkJoinPool----FJP先看task.fork方法,含义是将当前任务,放到当前线程的工作队列中.但是第一次执行这个方法是在主线程中,主线程是不可能被FJP管理的.那么就进入ForkJoi ...
- [原创] JAVA 递归线程池测试 ExecutorService / ForkJoinPool
测试工具使用递归的方式获取子进程的Msg消息,目前有2种常用的ExecutorService / ForkJoinPool 为了测试哪种效果较好,我们来写个测试Demo,循环5555555次+1(加锁 ...
- [Java并发编程(二)] 线程池 FixedThreadPool、CachedThreadPool、ForkJoinPool?为后台任务选择合适的 Java executors
[Java并发编程(二)] 线程池 FixedThreadPool.CachedThreadPool.ForkJoinPool?为后台任务选择合适的 Java executors ... 摘要 Jav ...
- (四)juc线程高级特性——线程池 / 线程调度 / ForkJoinPool
13. 线程池 第四种获取线程的方法:线程池,一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置. 线程池可以解决两个不同问 ...
- Java并发——Fork/Join框架与ForkJoinPool
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/4631466. ...
- 多线程 ForkJoinPool
阅读目录 使用 背景:ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行:当多个“小任务”执行完成 ...
- Java 多线程中的任务分解机制-ForkJoinPool,以及CompletableFuture
ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行:当多个“小任务”执行完成之后,再将这些执行结果 ...
随机推荐
- 构建Maven父子工程
IDEA构建maven父子工程: 1.打开IDEA,Create New Project 如图: 如果没有弹出新建界面,可以先 file-->Close Project 如图: 2.创建父 ...
- mobile_5 种常见适配_设备兼容
em 参照本身元素的 font-size rem 参照 html 根元素 的 font-size 1. rem 适配 (同一元素,在不同设备上,效果一样) 适用情况: 当页面大于 独立像素375 ...
- Solve Error: "errcode": 40016, "errmsg": "invalid button size hint"
在使用微信官方给的添加自定义菜单的示例代码: { "button": [ { "name": "扫码", "sub_button& ...
- Container/Injection
1.容器的历史 容器概念始于 1979 年提出的 UNIX chroot,它是一个 UNIX 操作系统的系统调用,将一个进程及其子进程的根目录改变到文件系统中的一个新位置,让这些进程只能访问到这个新的 ...
- python语法_字符串
字符串 a = 'asdb' #双引号和打印号没区别, 操作 "abc"*2 打印两遍"abc" #字符串 加* 重复打印字符串 “abc”[2:1] #切片 ...
- zhuan: WAN simulating tool - Netem : command tc qdisc
Last weekly meeting we talked about a WAN simulating tool in order to test WPG, I find a great tool ...
- JavaScript中innerHTML与innerText,createTextNode的区别
innerHTML和innerText 它们都会把元素内内容替换掉,区别在于: innerHTML 会把替换内容里的 HTML 标记解释执行. innerText 会把替换内容里的 HTML 标记原样 ...
- Install sublime text for elementary os
1. download sublime_text_3_build_3176_x86.tar.gz from http://www.sublimetext.com/3 2. extract it to ...
- 复制pdf文字出来是乱码
PDF文件复制文本为乱码 - longzhinuhou的博客 - CSDN博客 https://blog.csdn.net/longzhinuhou/article/details/83758966 ...
- complex类
#include<iostream> #include<cmath> using namespace std; class complex{ public: complex() ...