Fork/Join框架之Fork、Join操作
Fork
- if ((s -= queueBase) <= 2)
- pool.signalWork();
- else if (s == m)
- growQueue();
其中s=queueTop,m为数组length减1。else if部分,表示数组所有元素都满了,需要扩容,不难理解。if部分表示当数组元素比较少时(1或者2),就调用signalWork()方法。signalWork()方法做了两件事:1、唤配当前线程;2、当没有活动线程时或者线程数较少时,添加新的线程。
Join
- private int doJoin() {
- Thread t; ForkJoinWorkerThread w; int s; boolean completed;
- if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
- if ((s = status) < 0)
- return s;
- if ((w = (ForkJoinWorkerThread)t).unpushTask(this)) {
- try {
- completed = exec();
- } catch (Throwable rex) {
- return setExceptionalCompletion(rex);
- }
- if (completed)
- return setCompletion(NORMAL);
- }
- return w.joinTask(this);
- }
- else
- return externalAwaitDone();
- }
(1)第4行,(s=status)<0表示这个任务被执行完,直接返回执行结果状态,上层捕获到状态后,决定是要获取结果还是进行错误处理;
- final int joinTask(ForkJoinTask<?> joinMe) {
- ForkJoinTask<?> prevJoin = currentJoin;
- currentJoin = joinMe;
- for (int s, retries = MAX_HELP;;) {
- if ((s = joinMe.status) < 0) {
- currentJoin = prevJoin;
- return s;
- }
- if (retries > 0) {
- if (queueTop != queueBase) {
- if (!localHelpJoinTask(joinMe))
- retries = 0; // cannot help
- }
- else if (retries == MAX_HELP >>> 1) {
- --retries; // check uncommon case
- if (tryDeqAndExec(joinMe) >= 0)
- Thread.yield(); // for politeness
- }
- else
- retries = helpJoinTask(joinMe) ? MAX_HELP : retries - 1;
- }
- else {
- retries = MAX_HELP; // restart if not done
- pool.tryAwaitJoin(joinMe);
- }
- }
- }
(1)这里有个常量MAX_HELP=16,表示帮助join的次数。第11行,queueTop!=queueBase表示本地队列中有任务,如果这个任务刚好在队首,则尝试自己执行;否则返回false。这时retries被设置为0,表示不能帮助,因为自已队列不为空,自己并不空闲。在下一次循环就会进入第24行,等待这个任务执行完成。
- outer:for (ForkJoinWorkerThread thread = this;;) {
- // Try to find v, the stealer of task, by first using hint
- ForkJoinWorkerThread v = ws[thread.stealHint & m];
- if (v == null || v.currentSteal != task) {
- for (int j = 0; ;) { // search array
- if ((v = ws[j]) != null && v.currentSteal == task) {
- thread.stealHint = j;
- break; // save hint for next time
- }
- if (++j > m)
- break outer; // can't find stealer
- }
- }
- // Try to help v, using specialized form of deqTask
- for (;;) {
- ForkJoinTask<?>[] q; int b, i;
- if (joinMe.status < 0)
- break outer;
- if ((b = v.queueBase) == v.queueTop ||
- (q = v.queue) == null ||
- (i = (q.length-1) & b) < 0)
- break; // empty
- long u = (i << ASHIFT) + ABASE;
- ForkJoinTask<?> t = q[i];
- if (task.status < 0)
- break outer; // stale
- if (t != null && v.queueBase == b &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- v.queueBase = b + 1;
- v.stealHint = poolIndex;
- ForkJoinTask<?> ps = currentSteal;
- currentSteal = t;
- t.doExec();
- currentSteal = ps;
- helped = true;
- }
- }
- // Try to descend to find v's stealer
- ForkJoinTask<?> next = v.currentJoin;
- if (--levels > 0 && task.status >= 0 &&
- next != null && next != task) {
- task = next;
- thread = v;
- }
- }
(1)通过查看stealHint这个字段的注释可以知道,它表示最近一次谁来偷过我的queue中的任务。因此通过stealHint并不能找到当前任务被谁偷了?所以第4行v.currentSteal != task完全可能。这时还有一个办法找到这个任务被谁偷了,看看currentSteal这个字段的注释表示最近偷的哪个任务。这里扫描所有偷来的任务与当前任务比较,如果相等,就是这个线程偷的。如果这两种方法都不能找到小偷,只能等待了。
Fork/Join框架之Fork、Join操作的更多相关文章
- 《java.util.concurrent 包源码阅读》25 Fork/Join框架之Fork与Work-Stealing(重写23,24)
在写前面两篇文章23和24的时候自己有很多细节搞得不是很明白,这篇文章把Fork和Work-Stealing相关的源代码重新梳理一下. 首先来看一些线程池定义的成员变量: 关于scanGuard: v ...
- 《java.util.concurrent 包源码阅读》23 Fork/Join框架之Fork的冰山一角
上篇文章一直追踪到了ForkJoinWorkerThread的pushTask方法,仍然没有办法解释Fork的原理,那么不妨来看看ForkJoinWorkerThread的run方法: public ...
- 聊聊并发(八)——Fork/Join框架介绍
作者 方腾飞 发布于 2013年12月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 ...
- 转:聊聊并发(八)——Fork/Join框架介绍
1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...
- Fork/Join框架介绍
转http://www.infoq.com/cn/articles/fork-join-introduction/ 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用 ...
- Fork/Join 框架
本文部分摘自<Java 并发编程的艺术> Fork/Join 框架概述 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架,是把一个大任务分割成若干个小任务,最终汇总 ...
- Java 并发之 Fork/Join 框架
什么是 Fork/Join 框架 Fork/Join 框架是一种在 JDk 7 引入的线程池,用于并行执行把一个大任务拆成多个小任务并行执行,最终汇总每个小任务结果得到大任务结果的特殊任务.通过其命名 ...
- 多线程(五) Fork/Join框架介绍及实例讲解
什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过For ...
- JAVA中的Fork/Join框架
看了下Java Tutorials中的fork/join章节,整理下. 什么是fork/join框架 fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核 ...
- JAVA并行框架:Fork/Join
一.背景 虽然目前处理器核心数已经发展到很大数目,但是按任务并发处理并不能完全充分的利用处理器资源,因为一般的应用程序没有那么多的并发处理任务.基于这种现状,考虑把一个任务拆分成多个单元,每个单元分别 ...
随机推荐
- docker高级篇第三章-dockerfile案例之制作自己的centos镜像
在上一篇文章中<Dockerfile介绍及常用保留指令>,我们介绍了Dockerfile是什么以及Dockerfile常用的保留字段.熟悉了这些之后,有没有想自己动手写一个Dockerfi ...
- bacnet mstp设备数据 转IEC61850项目案例
目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 使用YABE软件读取BACNET MSTP设备信息 2 4 配置网关采集BACNET MSTP数据 4 5 用IEC61850协议转发数据 ...
- 【YashanDB知识库】手动停止统计信息自动收集任务导致的性能变差
[问题分类]功能使用 [关键字]统计信息收集 [问题描述]UAT对外演示环境因统计信息收集任务引起数据库整理性能变慢无应急处理手段 [问题原因分析] ● DROP_JOB程序用于删除一个非执行状态下的 ...
- Python将表格文件中某些列的数据整体向上移动一行
本文介绍基于Python语言,针对一个文件夹下大量的Excel表格文件,对其中的每一个文件加以操作--将其中指定的若干列的数据部分都向上移动一行,并将所有操作完毕的Excel表格文件中的数据加以合 ...
- 小tips:vue结合百度UEditor富文本编辑器实现vue-ueditor-wrap
1.下载vue-ueditor-wrap cnpm i vue-ueditor-wrap -S 下载最新的 UEditor 资源文件放入你项目的静态资源目录中(比如 static 或者 public, ...
- [namespace hdk] Balanced_tree 整合
代码 #include<bits/stdc++.h> using namespace std; namespace hdk{ namespace balanced_tree{ const ...
- Java远程连接服务器实现文件上传下载及目录操作
详情请阅读原文 在其基础之上做了进一步的封装 <!-- https://mvnrepository.com/artifact/com.jcraft/jsch --> <depende ...
- Salesforce AI Specialist篇之 Einstein Trust Layer
本篇参考: https://trailhead.salesforce.com/content/learn/trails/drive-productivity-with-einstein-ai http ...
- Electron.Net + Linux + Blazor 初尝备忘录
Electron 是使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序的一个框架, Electron.NET 是.net 下对 Electron 的封装实现, 通过它可以比较容 ...
- form data 与request payload的区别以及php接收这些数据的方法
form data 与request payload的区别以及php接收这些数据的方法 以前与前端交互一直都是POST.GET的,PHP端就直接$_POST,$_GET来接收,从来没有出现过以外. 最 ...