ForkJoinPool

  1. ForkJoinPool 是一个运行 ForkJoinTask 任务、支持工作窃取和并行计算的线程池

核心参数+创建实例

  1. // 工作者线程驻留任务队列索引位
  2. static final int SWIDTH = 16;
  3. // 低 16 位掩码
  4. static final int SMASK = 0xffff;
  5. // 最大并行度:#workers - 1
  6. static final int MAX_CAP = 0x7fff;
  7. // 最大工作队列数、提交队列数
  8. static final int SQMASK = 0x007e;
  9. // 工作者线程需要唤醒信号
  10. static final int UNSIGNALLED = 1 << 31; // must be negative
  11. // 防止 ABA 问题的版本号
  12. static final int SS_SEQ = 1 << 16;
  13. // 提交队列锁
  14. static final int QLOCK = 1;
  15. // 任务队列拥有所有者【驻留线程】
  16. static final int OWNED = 1;
  17. // 任务是先进先出的
  18. static final int FIFO = 1 << 16;
  19. // 线程池正在关闭
  20. static final int SHUTDOWN = 1 << 18;
  21. // 线程池已经停止
  22. static final int TERMINATED = 1 << 19;
  23. // 线程池正在停止
  24. static final int STOP = 1 << 31; // must be negative
  25. // 任务队列处于静止状态
  26. static final int QUIET = 1 << 30;
  27. // 任务队列处于静止状态 && 驻留线程已经阻塞、需要唤醒信号
  28. static final int DORMANT = QUIET | UNSIGNALLED;
  29. /**
  30. * 工作者线程能在驻留的工作队列中一次性处理的最大任务数
  31. */
  32. static final int POLL_LIMIT = 1 << 10;
  33. /**
  34. * 默认的工作者线程工厂
  35. */
  36. public static final ForkJoinWorkerThreadFactory
  37. defaultForkJoinWorkerThreadFactory;
  38. /**
  39. * Common (static) pool. 通用 ForkJoinPool
  40. */
  41. static final ForkJoinPool common;
  42. /**
  43. * 通用线程池的并行度
  44. */
  45. static final int COMMON_PARALLELISM;
  46. /**
  47. * 通用线程池最大补偿的工作线程数
  48. */
  49. private static final int COMMON_MAX_SPARES;
  50. /**
  51. * 线程池序列号,用于生成工作者线程名称
  52. */
  53. private static int poolNumberSequence;
  54. /**
  55. * 默认的工作者线程超时时间,以毫秒为单位,即 60 秒
  56. */
  57. private static final long DEFAULT_KEEPALIVE = 60_000L;
  58. /**
  59. * Undershoot tolerance for idle timeouts【超时微调】
  60. */
  61. private static final long TIMEOUT_SLOP = 20L;
  62. private static final int DEFAULT_COMMON_MAX_SPARES = 256;
  63. private static final int SEED_INCREMENT = 0x9e3779b9;
  64. /**
  65. * 64 位控制变量的组成,从高到低每 16 位一个单元
  66. * RC: 正在运行的工作者线程数 - parallelism
  67. * TC: 正在运行的工作者线程数 + 阻塞等待的工作者线程数 - parallelism
  68. * SS: 版本号 + 最近阻塞的线程状态
  69. * ID: 最近阻塞的工作者线程所在的工作队列索引
  70. *
  71. * ac 为负数:表示运行中的工作者线程不够
  72. * tc 为负数:表示总的工作者线程不够
  73. * sp != 0:表示有工作者线程在阻塞等待
  74. */
  75. private static final long SP_MASK = 0xffffffffL;
  76. private static final long UC_MASK = ~SP_MASK;
  77. private static final int RC_SHIFT = 48;
  78. // 单个工作者线程计数,用于 RC
  79. private static final long RC_UNIT = 0x0001L << RC_SHIFT;
  80. // 控制变量 48-64 位掩码
  81. private static final long RC_MASK = 0xffffL << RC_SHIFT;
  82. private static final int TC_SHIFT = 32;
  83. // 单个工作者线程计数,用于 TC
  84. private static final long TC_UNIT = 0x0001L << TC_SHIFT;
  85. // 控制变量 32-48 位掩码
  86. private static final long TC_MASK = 0xffffL << TC_SHIFT;
  87. // 尝试增加一个工作者线程,工作者线程数 < parallelism
  88. private static final long ADD_WORKER = 0x0001L << TC_SHIFT + 15; // sign
  89. // 工作者线程的窃取任务总数
  90. volatile long stealCount;
  91. // 工作者线程的空闲存活时间
  92. final long keepAlive;
  93. // 下一个工作队列索引
  94. int indexSeed;
  95. // 最大、最小线程数
  96. final int bounds;
  97. /**
  98. * runstate:第 18、19、30、31 位
  99. * queue mode:第 16 位
  100. * parallelism:1-15 位,最大并行度为 1<<15-1
  101. */
  102. volatile int mode;
  103. // 已注册的工作队列
  104. WorkQueue[] workQueues;
  105. // 工作者线程名称前缀,同时作为创建工作队列时的 synchronized 锁
  106. final String workerNamePrefix;
  107. // 创建工作者线程的工厂
  108. final ForkJoinWorkerThreadFactory factory;
  109. // 异常处理器
  110. final UncaughtExceptionHandler ueh;
  111. // 线程池饱和断言
  112. final Predicate<? super ForkJoinPool> saturate;
  113. // 核心控制变量
  114. @jdk.internal.vm.annotation.Contended("fjpctl")
  115. volatile long ctl;
  116. public ForkJoinPool() {
  117. /**
  118. * 1)并行度为当前 JVM 的 CPU 总数 Runtime.getRuntime().availableProcessors()
  119. * 2)使用默认的线程工厂
  120. * 3)无异常处理器
  121. * 4)工作队列的任务处理方式为 FILO
  122. * 提交队列的任务处理方式为 FIFO,工作窃取
  123. * 5)默认的核心工作者线程数为 0
  124. * 6)默认的最大工作者线程数为 32767
  125. * 7)默认工作者线程空闲超时时间为 60 秒
  126. */
  127. this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
  128. defaultForkJoinWorkerThreadFactory, null, false,
  129. 0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
  130. }
  131. /**
  132. * @param parallelism 并行度【影响任务队列的长度和工作者线程数】
  133. */
  134. public ForkJoinPool(int parallelism) {
  135. this(parallelism, defaultForkJoinWorkerThreadFactory, null, false,
  136. 0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
  137. }
  138. /**
  139. * @param parallelism 并行度
  140. * @param factory 工作者线程工厂
  141. * @param handler 异常处理器
  142. * @param asyncMode 任务处理模式
  143. */
  144. public ForkJoinPool(int parallelism,
  145. ForkJoinWorkerThreadFactory factory,
  146. UncaughtExceptionHandler handler,
  147. boolean asyncMode) {
  148. this(parallelism, factory, handler, asyncMode,
  149. 0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
  150. }
  151. /**
  152. * @param parallelism ForkJoinPool 的并行度
  153. * @param factory 工作者线程工厂
  154. * @param handler 每个工作者线程的异常处理器
  155. * @param asyncMode 工作队列的任务处理模式,默认是 false【FILO】,
  156. * 消息模式下可以指定为 FIFO
  157. * @param corePoolSize 核心工作者线程数,默认等于 parallelism
  158. * @param maximumPoolSize 最大工作者线程数
  159. * @param minimumRunnable 最小可用工作者线程数
  160. * @param saturate 当线程池尝试创建 > maximumPoolSize 的工作者线程时,目标任务将被拒绝,
  161. * 如果饱和断言返回 true,则该任务将继续执行
  162. * @param keepAliveTime 工作线程的空闲超时时间
  163. * @param unit keepAliveTime 的时间单位
  164. * @since 9
  165. */
  166. public ForkJoinPool(int parallelism,
  167. ForkJoinWorkerThreadFactory factory,
  168. UncaughtExceptionHandler handler,
  169. boolean asyncMode,
  170. int corePoolSize,
  171. int maximumPoolSize,
  172. int minimumRunnable,
  173. Predicate<? super ForkJoinPool> saturate,
  174. long keepAliveTime,
  175. TimeUnit unit) {
  176. // check, encode, pack parameters
  177. if (parallelism <= 0 || parallelism > MAX_CAP ||
  178. maximumPoolSize < parallelism || keepAliveTime <= 0L) {
  179. throw new IllegalArgumentException();
  180. }
  181. if (factory == null) {
  182. throw new NullPointerException();
  183. }
  184. // 计算超时时间
  185. final long ms = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);
  186. // 核心工作者线程数
  187. final int corep = Math.min(Math.max(corePoolSize, parallelism), MAX_CAP);
  188. // 计算 ctl
  189. final long c = (long)-corep << TC_SHIFT & TC_MASK |
  190. (long)-parallelism << RC_SHIFT & RC_MASK;
  191. // 计算 mode
  192. final int m = parallelism | (asyncMode ? FIFO : 0);
  193. final int maxSpares = Math.min(maximumPoolSize, MAX_CAP) - parallelism;
  194. // 最小可用工作者线程数
  195. final int minAvail = Math.min(Math.max(minimumRunnable, 0), MAX_CAP);
  196. final int b = minAvail - parallelism & SMASK | maxSpares << SWIDTH;
  197. int n = parallelism > 1 ? parallelism - 1 : 1; // at least 2 slots
  198. n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
  199. n = n + 1 << 1; // power of two, including space for submission queues
  200. workerNamePrefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
  201. workQueues = new WorkQueue[n];
  202. this.factory = factory;
  203. ueh = handler;
  204. this.saturate = saturate;
  205. keepAlive = ms;
  206. bounds = b;
  207. mode = m;
  208. ctl = c;
  209. checkPermission();
  210. }

提交任务

  1. /**
  2. * 往线程池中提交一个 Runnable 任务
  3. */
  4. @Override
  5. @SuppressWarnings("unchecked")
  6. public ForkJoinTask<?> submit(Runnable task) {
  7. if (task == null) {
  8. throw new NullPointerException();
  9. }
  10. // 如果 task 不是 ForkJoinTask 子类实例,则执行适配
  11. return externalSubmit(task instanceof ForkJoinTask<?>
  12. ? (ForkJoinTask<Void>) task // avoid re-wrap
  13. : new ForkJoinTask.AdaptedRunnableAction(task));
  14. }
  15. private <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) {
  16. Thread t; ForkJoinWorkerThread w; WorkQueue q;
  17. if (task == null) {
  18. throw new NullPointerException();
  19. }
  20. /**
  21. * 1)如果任务提交线程是 ForkJoinWorkerThread 实例 &&
  22. * 工作者线程关联的 ForkJoinPool 就是当前线程池 &&
  23. * 工作者线程驻留的任务队列不为 null
  24. * 则优先提交到自己的任务队列
  25. */
  26. if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread &&
  27. (w = (ForkJoinWorkerThread)t).pool == this &&
  28. (q = w.workQueue) != null) {
  29. q.push(task);
  30. // 2)将任务提交到共享提交队列
  31. } else {
  32. externalPush(task);
  33. }
  34. return task;
  35. }
  36. ForkJoinTask#
  37. /**
  38. * 将 Runnable 任务适配为 ForkJoinTask 任务
  39. */
  40. static final class AdaptedRunnableAction extends ForkJoinTask<Void>
  41. implements RunnableFuture<Void> {
  42. /**
  43. * 实际运行的任务
  44. */
  45. final Runnable runnable;
  46. AdaptedRunnableAction(Runnable runnable) {
  47. if (runnable == null) {
  48. throw new NullPointerException();
  49. }
  50. this.runnable = runnable;
  51. }
  52. @Override
  53. public Void getRawResult() { return null; }
  54. @Override
  55. public void setRawResult(Void v) { }
  56. // 运行 Runnable 任务
  57. @Override
  58. public boolean exec() { runnable.run(); return true; }
  59. @Override
  60. public void run() { invoke(); }
  61. @Override
  62. public String toString() {
  63. return super.toString() + "[Wrapped task = " + runnable + "]";
  64. }
  65. private static final long serialVersionUID = 5232453952276885070L;
  66. }
  67. /**
  68. * 将一个 ForkJoinTask 提交到一个提交队列中
  69. */
  70. final void externalPush(ForkJoinTask<?> task) {
  71. int r; // initialize caller's probe
  72. // 如果调用线程的探测值为 0
  73. if ((r = ThreadLocalRandom.getProbe()) == 0) {
  74. // 初始化线程局部随机数的探测值
  75. ThreadLocalRandom.localInit();
  76. /**
  77. * 读取探测值【同一个线程只要不调用 advanceProbe 方法,探测值是不变的,
  78. * 同一个线程提交任务时只要不出现竞争,就会将任务提交到相同的提交队列中】
  79. */
  80. r = ThreadLocalRandom.getProbe();
  81. }
  82. for (;;) {
  83. // 读取 mode
  84. final int md = mode;
  85. int n;
  86. // 读取工作队列
  87. WorkQueue[] ws = workQueues;
  88. // 线程池已经设置了 SHUTDOWN 标识 || 工作队列为空,则拒绝提交任务
  89. if ((md & SHUTDOWN) != 0 || ws == null || (n = ws.length) <= 0) {
  90. throw new RejectedExecutionException();
  91. } else {
  92. WorkQueue q;
  93. // push 是否添加成功,grow 是否需要进行扩容
  94. boolean push = false, grow = false;
  95. // 1)基于探测值掩码定位到指定索引的任务队列,如果该任务队列还未创建
  96. if ((q = ws[n - 1 & r & SQMASK]) == null) {
  97. // 读取工作者名称前缀
  98. final Object lock = workerNamePrefix;
  99. /**
  100. * 基于探测值、队列静止标识、非 FIFO 标识、无所有者标识
  101. * 生成队列 ID
  102. */
  103. final int qid = (r | QUIET) & ~(FIFO | OWNED);
  104. // 创建提交队列
  105. q = new WorkQueue(this, null);
  106. // 写入队列 ID
  107. q.id = qid;
  108. // 队列设置为静止状态
  109. q.source = QUIET;
  110. // 锁定队列
  111. q.phase = QLOCK; // lock queue
  112. if (lock != null) {
  113. // 同步锁定队列
  114. synchronized (lock) { // lock pool to install
  115. int i;
  116. /**
  117. * 再次判断指定目标索引下的任务队列是否还为空,
  118. * 出现竞争时可能被其他线程提前写入
  119. */
  120. if ((ws = workQueues) != null &&
  121. (n = ws.length) > 0 &&
  122. ws[i = qid & n - 1 & SQMASK] == null) {
  123. // 写入新建队列
  124. ws[i] = q;
  125. // 新建队列后需要扩容,并提交任务
  126. push = grow = true;
  127. }
  128. }
  129. }
  130. }
  131. // 2)提交队列已经存在,则尝试获得共享锁
  132. else if (q.tryLockSharedQueue()) {
  133. // 获取锁成功,读取 base 和 top 值
  134. final int b = q.base, s = q.top;
  135. int al, d; ForkJoinTask<?>[] a;
  136. // 1)提交队列的任务数组不为空 && 任务数组未满
  137. if ((a = q.array) != null && (al = a.length) > 0 &&
  138. al - 1 + (d = b - s) > 0) {
  139. // 基于 top 值定位数组索引后写入任务
  140. a[al - 1 & s] = task;
  141. // 递增 top 值并写入
  142. q.top = s + 1; // relaxed writes OK here
  143. // 释放共享锁
  144. q.phase = 0;
  145. // 队列中有多于 1 个任务
  146. if (d < 0 && q.base - s < -1)
  147. {
  148. break; // no signal needed
  149. }
  150. // 数组已满则需要进行扩容
  151. } else {
  152. grow = true;
  153. }
  154. // 添加任务成功
  155. push = true;
  156. }
  157. if (push) {
  158. // 如果需要执行扩容
  159. if (grow) {
  160. try {
  161. // 执行任务队列的扩容
  162. q.growArray();
  163. // 读取 top 值
  164. final int s = q.top;
  165. int al; ForkJoinTask<?>[] a;
  166. if ((a = q.array) != null && (al = a.length) > 0) {
  167. // 写入任务
  168. a[al - 1 & s] = task;
  169. // 递增 top 值并写入
  170. q.top = s + 1;
  171. }
  172. } finally {
  173. // 释放共享锁
  174. q.phase = 0;
  175. }
  176. }
  177. // 添加任务成功,则尝试添加或唤醒工作者线程
  178. signalWork();
  179. break;
  180. } else {
  181. // 出现线程竞争时,重新生成探测值并进行重试
  182. r = ThreadLocalRandom.advanceProbe(r);
  183. }
  184. }
  185. }
  186. }
  187. static final class WorkQueue {
  188. /**
  189. * 任务数组的初始化容量为 8192
  190. */
  191. static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
  192. /**
  193. * 任务数组的最大容量
  194. */
  195. static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
  196. /**
  197. * 值为负数:
  198. * 1)(任务队列的 ID +累计版本号) | UNSIGNALLED
  199. * 2)DORMANT:任务队列处于静止状态 && 驻留线程已经阻塞、需要唤醒信号
  200. * 0:队列未锁定
  201. * 1:队列被锁定
  202. */
  203. volatile int phase;
  204. // 队列进入静止状态时的控制变量值,可能包含前一个静止的任务队列信息
  205. int stackPred;
  206. // 工作者线程窃取的任务数
  207. int nsteals;
  208. int id; // index, mode, tag
  209. // 上一次窃取的工作队列 ID 或哨兵值
  210. volatile int source;
  211. // 执行 poll 操作的索引
  212. volatile int base;
  213. // 执行 push 或 pop 操作的索引
  214. int top;
  215. // 底层存储 ForkJoinTask 的数组
  216. ForkJoinTask<?>[] array;
  217. // 任务队列所在的线程池
  218. final ForkJoinPool pool;
  219. // 工作队列驻留的工作者线程,共享提交队列为 null
  220. final ForkJoinWorkerThread owner;
  221. /**
  222. * 尝试锁定共享提交队列
  223. */
  224. boolean tryLockSharedQueue() {
  225. return PHASE.compareAndSet(this, 0, QLOCK);
  226. }
  227. /**
  228. * 初始化队列或执行双倍扩容
  229. */
  230. ForkJoinTask<?>[] growArray() {
  231. // 读取旧队列
  232. final ForkJoinTask<?>[] oldA = array;
  233. // 读取旧 size
  234. final int oldSize = oldA != null ? oldA.length : 0;
  235. // 计算新 size,初始化容量为 8192
  236. final int size = oldSize > 0 ? oldSize << 1 : INITIAL_QUEUE_CAPACITY;
  237. // size 小于 8192 或大于 64M
  238. if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY) {
  239. // 扩容失败则抛出 RejectedExecutionException 异常,任务被拒绝
  240. throw new RejectedExecutionException("Queue capacity exceeded");
  241. }
  242. int oldMask, t, b;
  243. // 基于新的 size 创建 ForkJoinTask 数组
  244. final ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
  245. // 旧数组中有任务存在,则执行迁移操作
  246. if (oldA != null && (oldMask = oldSize - 1) > 0 &&
  247. (t = top) - (b = base) > 0) {
  248. // 计算新任务数组的 mask
  249. final int mask = size - 1;
  250. do { // emulate poll from old array, push to new array
  251. // 从 base 开始迁移任务
  252. final int index = b & oldMask;
  253. // 读取任务
  254. final ForkJoinTask<?> x = (ForkJoinTask<?>)
  255. QA.getAcquire(oldA, index);
  256. // 将旧数组中对应的 slot 置为 null
  257. if (x != null &&
  258. QA.compareAndSet(oldA, index, x, null)) {
  259. // 写入新数组
  260. a[b & mask] = x;
  261. }
  262. // 循环迁移
  263. } while (++b != t);
  264. VarHandle.releaseFence();
  265. }
  266. // 返回新数组
  267. return a;
  268. }
  269. }
  270. /**
  271. * 尝试创建或唤醒一个工作者
  272. */
  273. final void signalWork() {
  274. for (;;) {
  275. long c; int sp; WorkQueue[] ws; int i; WorkQueue v;
  276. // 1)活跃工作者线程数已经 >= 并行度
  277. if ((c = ctl) >= 0L) {
  278. break;
  279. // 2)核心工作者线程未满 && 无空闲工作者线程
  280. } else if ((sp = (int)c) == 0) { // no idle workers
  281. if ((c & ADD_WORKER) != 0L) {
  282. // 尝试增加一个工作者线程
  283. tryAddWorker(c);
  284. }
  285. break;
  286. }
  287. // 3)workQueues 为 null 表示线程池未启动或已经终止
  288. else if ((ws = workQueues) == null) {
  289. break; // unstarted/terminated
  290. // 4)线程池已经终止
  291. } else if (ws.length <= (i = sp & SMASK)) {
  292. break; // terminated
  293. // 5)线程池正在终止,目标工作队列已经被回收
  294. } else if ((v = ws[i]) == null) {
  295. break; // terminating
  296. // 6)核心工作者线程未满 && 有工作者线程静止或已经阻塞
  297. } else {
  298. // 读取最近静止的工作队列 ID 及其工作队列索引
  299. final int np = sp & ~UNSIGNALLED;
  300. // 读取工作队列的 phase 值
  301. final int vp = v.phase;
  302. /**
  303. * 读取在这个工作队列静止或工作者线程阻塞前,
  304. * 上一个静止的工作者队列或阻塞的工作者线程所处的控制变量
  305. */
  306. final long nc = v.stackPred & SP_MASK | UC_MASK & c + RC_UNIT;
  307. // 读取工作队列驻留线程
  308. final Thread vt = v.owner;
  309. // 如果当前工作队列是最近静止的或其工作者线程是最近阻塞的,则尝试恢复为静止之前的控制变量
  310. if (sp == vp && CTL.compareAndSet(this, c, nc)) {
  311. // 写入 phase 值
  312. v.phase = np;
  313. // 如果 source 为 DORMANT【工作者线程阻塞前一刻写入】
  314. if (v.source < 0) {
  315. // 唤醒阻塞的工作者线程
  316. LockSupport.unpark(vt);
  317. }
  318. break;
  319. }
  320. }
  321. }
  322. }
  323. /**
  324. * 尝试增加一个工作者线程
  325. * Tries to add one worker, incrementing ctl counts before doing
  326. * so, relying on createWorker to back out on failure.
  327. */
  328. private void tryAddWorker(long c) {
  329. do {
  330. // 活跃工作者线程数和总的工作者线程数,递增 1
  331. final long nc = RC_MASK & c + RC_UNIT |
  332. TC_MASK & c + TC_UNIT;
  333. // 如果控制变量未更新 && 原子更新当前控制变量成功
  334. if (ctl == c && CTL.compareAndSet(this, c, nc)) {
  335. // 创建一个新的工作者线程
  336. createWorker();
  337. break;
  338. }
  339. // 出现竞争,则重新判断并重试
  340. } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
  341. }
  342. /**
  343. * 尝试创建并启动一个新的工作者线程
  344. */
  345. private boolean createWorker() {
  346. // 读取工作者线程工厂
  347. final ForkJoinWorkerThreadFactory fac = factory;
  348. Throwable ex = null;
  349. ForkJoinWorkerThread wt = null;
  350. try {
  351. // 创建一个新的工作者线程
  352. if (fac != null && (wt = fac.newThread(this)) != null) {
  353. // 启动工作线程
  354. wt.start();
  355. return true;
  356. }
  357. } catch (final Throwable rex) {
  358. ex = rex;
  359. }
  360. // 创建失败或启动失败,则注销当前工作者
  361. deregisterWorker(wt, ex);
  362. return false;
  363. }
  364. final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
  365. WorkQueue w = null;
  366. int phase = 0;
  367. // 目标工作者线程不为 null && 任务队列不为 null
  368. if (wt != null && (w = wt.workQueue) != null) {
  369. final Object lock = workerNamePrefix;
  370. // 计算窃取任务数
  371. final long ns = w.nsteals & 0xffffffffL;
  372. // 计算工作队列索引
  373. final int idx = w.id & SMASK;
  374. if (lock != null) {
  375. WorkQueue[] ws; // remove index from array
  376. synchronized (lock) {
  377. // 将工作者线程驻留的任务队列回收
  378. if ((ws = workQueues) != null && ws.length > idx &&
  379. ws[idx] == w) {
  380. ws[idx] = null;
  381. }
  382. // 累积总的窃取任务数
  383. stealCount += ns;
  384. }
  385. }
  386. // 读取工作队列 phase 值
  387. phase = w.phase;
  388. }
  389. // 工作队列不是静止状态
  390. if (phase != QUIET) { // else pre-adjusted
  391. long c; // decrement counts
  392. // 活跃工作者线程数和总工作者线程数递减 1
  393. do {} while (!CTL.weakCompareAndSet
  394. (this, c = ctl, RC_MASK & c - RC_UNIT |
  395. TC_MASK & c - TC_UNIT |
  396. SP_MASK & c));
  397. }
  398. // 如果工作者线程驻留的工作队列不为 null
  399. if (w != null)
  400. {
  401. // 取消所有的任务
  402. w.cancelAll(); // cancel remaining tasks
  403. }
  404. /**
  405. * 终止线程池失败 && 工作队列不为 null && 任务数组不为 null
  406. */
  407. if (!tryTerminate(false, false) && // possibly replace worker
  408. w != null && w.array != null) {
  409. // 尝试创建或唤醒一个工作者线程
  410. signalWork();
  411. }
  412. // 1)如果不是异常终止,则删除过时的异常信息
  413. if (ex == null) {
  414. ForkJoinTask.helpExpungeStaleExceptions();
  415. } else {
  416. // 2)重新抛出异常
  417. ForkJoinTask.rethrow(ex);
  418. }
  419. }
  420. * @param now
  421. * true 表示无条件终止,
  422. * false 表示等到线程池无任务或无活跃工作者线程之后终止
  423. * @param enable true 可能在下次终止
  424. * @return true if terminating or terminated
  425. */
  426. private boolean tryTerminate(boolean now, boolean enable) {
  427. int md; // 3 phases: try to set SHUTDOWN, then STOP, then TERMINATED
  428. // 线程池状态不是 SHUTDOWN
  429. while (((md = mode) & SHUTDOWN) == 0) {
  430. /**
  431. * enable 为 false 和通用线程池不允许终止
  432. */
  433. if (!enable || this == common) {
  434. return false;
  435. } else {
  436. // 设置线程池状态为 SHUTDOWN
  437. MODE.compareAndSet(this, md, md | SHUTDOWN);
  438. }
  439. }
  440. while (((md = mode) & STOP) == 0) { // try to initiate termination
  441. // 如果不是立刻终止
  442. if (!now) { // check if quiescent & empty
  443. for (long oldSum = 0L;;) { // repeat until stable
  444. boolean running = false;
  445. long checkSum = ctl;
  446. final WorkQueue[] ws = workQueues;
  447. // 1)有活跃的工作者线程
  448. if ((md & SMASK) + (int)(checkSum >> RC_SHIFT) > 0) {
  449. running = true;
  450. // 2)工作队列不为 null
  451. } else if (ws != null) {
  452. WorkQueue w; int b;
  453. // 遍历所有的工作队列,看是否有未完成的任务
  454. for (int i = 0; i < ws.length; ++i) {
  455. if ((w = ws[i]) != null) {
  456. checkSum += (b = w.base) + w.id;
  457. if (b != w.top ||
  458. (i & 1) == 1 && w.source >= 0) {
  459. // 工作队列中有任务未完成
  460. running = true;
  461. break;
  462. }
  463. }
  464. }
  465. }
  466. // 1)线程池已经停止,则直接退出
  467. if (((md = mode) & STOP) != 0) {
  468. break; // already triggered
  469. // 2)有活跃工作者线程或有任务未完成,则返回 false
  470. } else if (running) {
  471. return false;
  472. } else if (workQueues == ws && oldSum == (oldSum = checkSum)) {
  473. break;
  474. }
  475. }
  476. }
  477. // 设置线程池状态为 STOP
  478. if ((md & STOP) == 0) {
  479. MODE.compareAndSet(this, md, md | STOP);
  480. }
  481. }
  482. // 线程池状态不是 TERMINATED
  483. while (((md = mode) & TERMINATED) == 0) { // help terminate others
  484. for (long oldSum = 0L;;) { // repeat until stable
  485. WorkQueue[] ws; WorkQueue w;
  486. long checkSum = ctl;
  487. // workQueues 不为空
  488. if ((ws = workQueues) != null) {
  489. for (final WorkQueue element : ws) {
  490. // 当前任务队列不为 null
  491. if ((w = element) != null) {
  492. final ForkJoinWorkerThread wt = w.owner;
  493. // 取消所有的任务
  494. w.cancelAll(); // clear queues
  495. // 如果是工作队列
  496. if (wt != null) {
  497. try { // unblock join or park
  498. // 中断工作者线程
  499. wt.interrupt();
  500. } catch (final Throwable ignore) {
  501. }
  502. }
  503. // 累加校验和
  504. checkSum += w.base + w.id;
  505. }
  506. }
  507. }
  508. if (((md = mode) & TERMINATED) != 0 ||
  509. workQueues == ws && oldSum == (oldSum = checkSum)) {
  510. break;
  511. }
  512. }
  513. // 1)线程池已经终止
  514. if ((md & TERMINATED) != 0) {
  515. break;
  516. // 2)还有工作者线程未中断
  517. } else if ((md & SMASK) + (short)(ctl >>> TC_SHIFT) > 0) {
  518. break;
  519. // 3)设置线程池状态为 TERMINATED
  520. } else if (MODE.compareAndSet(this, md, md | TERMINATED)) {
  521. synchronized (this) {
  522. notifyAll(); // for awaitTermination
  523. }
  524. break;
  525. }
  526. }
  527. // 终止成功返回 true
  528. return true;
  529. }
  530. WorkQueue#
  531. /**
  532. * 工作者线程将任务提交到自己驻留的工作队列中
  533. */
  534. void push(ForkJoinTask<?> task) {
  535. // 读取 top 索引
  536. final int s = top; ForkJoinTask<?>[] a; int al, d;
  537. /**
  538. * 1)保存任务的 ForkJoinTask 数组不为 null && 长度 > 0
  539. */
  540. if ((a = array) != null && (al = a.length) > 0) {
  541. // 基于旧的 top 索引计算任务存放的索引
  542. final int index = al - 1 & s;
  543. final ForkJoinPool p = pool;
  544. // 递增 top 索引
  545. top = s + 1;
  546. // 将任务存储到 ForkJoinTask 数组中
  547. QA.setRelease(a, index, task);
  548. // 1)如果是工作队列的第一个任务 && pool 不为 null
  549. if ((d = base - s) == 0 && p != null) {
  550. VarHandle.fullFence();
  551. // 尝试新增或唤醒工作者线程
  552. p.signalWork();
  553. }
  554. // 2)如果任务队列已满,则执行扩容
  555. else if (d + al == 1) {
  556. growArray();
  557. }
  558. }
  559. }

工作者线程的执行逻辑

  1. public class ForkJoinWorkerThread extends Thread {
  2. // 工作者线程所属的线程池
  3. final ForkJoinPool pool;
  4. // 工作者驻留的任务队列
  5. final ForkJoinPool.WorkQueue workQueue;
  6. /**
  7. * 创建一个在目标 pool 中执行任务的 ForkJoinWorkerThread 实例
  8. */
  9. protected ForkJoinWorkerThread(ForkJoinPool pool) {
  10. super("aForkJoinWorkerThread");
  11. this.pool = pool;
  12. // 将当前工作者线程注册到线程池中
  13. this.workQueue = pool.registerWorker(this);
  14. }
  15. /**
  16. * 工作线程启动前的钩子函数
  17. */
  18. protected void onStart() {
  19. }
  20. /**
  21. * 工作者线程退出后的钩子函数
  22. */
  23. protected void onTermination(Throwable exception) {
  24. }
  25. /**
  26. * 运行工作者线程
  27. */
  28. public void run() {
  29. if (workQueue.array == null) { // only run once
  30. Throwable exception = null;
  31. try {
  32. // 前置钩子
  33. onStart();
  34. // 运行工作队列
  35. pool.runWorker(workQueue);
  36. } catch (Throwable ex) {
  37. exception = ex;
  38. } finally {
  39. try {
  40. // 后置钩子
  41. onTermination(exception);
  42. } catch (Throwable ex) {
  43. if (exception == null)
  44. exception = ex;
  45. } finally {
  46. // 注销工作者
  47. pool.deregisterWorker(this, exception);
  48. }
  49. }
  50. }
  51. }
  52. /**
  53. * 工作者线程执行完驻留队列的任务后,会触发一次 afterTopLevelExec 回调
  54. */
  55. void afterTopLevelExec() {
  56. }
  57. }
  58. ForkJoinPool#
  59. /**
  60. * 工作者线程的核心运行逻辑
  61. */
  62. final void runWorker(WorkQueue w) {
  63. WorkQueue[] ws;
  64. // 执行任务数组的初始化
  65. w.growArray(); // allocate queue
  66. // 计算随机窃取任务的任务队列索引
  67. int r = w.id ^ ThreadLocalRandom.nextSecondarySeed();
  68. if (r == 0) {
  69. r = 1;
  70. }
  71. int lastSignalId = 0; // avoid unneeded signals
  72. // 循环处理
  73. while ((ws = workQueues) != null) {
  74. boolean nonempty = false; // scan
  75. /**
  76. * n:length
  77. * m:mask
  78. * b:base
  79. * i:index
  80. * a:array
  81. * q:WorkQueue
  82. * al:array length
  83. */
  84. for (int n = ws.length, j = n, m = n - 1; j > 0; --j) {
  85. WorkQueue q; int i, b, al; ForkJoinTask<?>[] a;
  86. /**
  87. * 1)基于随机索引定位的任务队列不为 null &&
  88. * 目标任务队列中有任务需要处理 &&
  89. * 目标任务队列的任务数组不为空
  90. */
  91. if ((i = r & m) >= 0 && i < n && // always true
  92. (q = ws[i]) != null && (b = q.base) - q.top < 0 &&
  93. (a = q.array) != null && (al = a.length) > 0) {
  94. // 被窃取任务队列的 ID
  95. final int qid = q.id; // (never zero)
  96. // 计算任务索引,窃取任务是从 base 开始的
  97. final int index = al - 1 & b;
  98. // 读取目标任务
  99. final ForkJoinTask<?> t = (ForkJoinTask<?>)
  100. QA.getAcquire(a, index);
  101. // 任务被当前线程获取,未出现竞争
  102. if (t != null && b++ == q.base &&
  103. QA.compareAndSet(a, index, t, null)) {
  104. /**
  105. * 当前任务队列里还有任务待处理 &&
  106. * 第一次窃取该任务队列里的任务
  107. */
  108. if ((q.base = b) - q.top < 0 && qid != lastSignalId)
  109. {
  110. // 尝试增加或唤醒一个工作者线程来帮忙处理任务
  111. signalWork(); // propagate signal
  112. }
  113. // 写入上一次窃取的任务队列 ID
  114. w.source = lastSignalId = qid;
  115. // 执行目标任务
  116. t.doExec();
  117. // 1)当前工作队列如果是 FIFO 模式
  118. if ((w.id & FIFO) != 0) {
  119. // 则从 base 位置开始处理自己的任务
  120. w.localPollAndExec(POLL_LIMIT);
  121. } else {
  122. // 则从 top 位置开始处理自己的任务
  123. w.localPopAndExec(POLL_LIMIT);
  124. }
  125. // 读取工作队列驻留线程
  126. final ForkJoinWorkerThread thread = w.owner;
  127. // 递增窃取任务数
  128. ++w.nsteals;
  129. // 重置窃取任务队列 ID
  130. w.source = 0; // now idle
  131. if (thread != null) {
  132. // 驻留线程不为 null,则执行 afterTopLevelExec 回调
  133. thread.afterTopLevelExec();
  134. }
  135. }
  136. // 处理完一个任务之后,再次尝试窃取该任务队列里的任务
  137. nonempty = true;
  138. }
  139. // 2)如果目标任务队列里的任务已经处理完毕,则退出此次扫描【一次只处理一个任务队列】
  140. else if (nonempty) {
  141. break;
  142. // 3)定位到的任务队列无任务可处理,则扫描下一个任务队列
  143. } else {
  144. ++r;
  145. }
  146. }
  147. // 1)如果成功处理完一个任务队列里的任务,则重新进行定位
  148. if (nonempty) { // move (xorshift)
  149. r ^= r << 13; r ^= r >>> 17; r ^= r << 5;
  150. }
  151. // 2)扫描了所有的任务队列都没有任务可处理
  152. else {
  153. int phase;
  154. // 重置 lastSignalId
  155. lastSignalId = 0; // clear for next scan
  156. // 1)如果队列还未进入静止状态
  157. if ((phase = w.phase) >= 0) { // enqueue
  158. // 写入队列 ID 及其工作队列索引
  159. final int np = w.phase = phase + SS_SEQ | UNSIGNALLED;
  160. long c, nc;
  161. do {
  162. // 记录先前的控制变量到 stackPred 中
  163. w.stackPred = (int)(c = ctl);
  164. // 活跃工作者数递减 1,同时写入 np
  165. nc = c - RC_UNIT & UC_MASK | SP_MASK & np;
  166. // 将当前队列的状态写入控制变量中,写入成功后尝试执行最后一次扫描
  167. } while (!CTL.weakCompareAndSet(this, c, nc));
  168. }
  169. else { // already queued
  170. // 读取 stackPred
  171. final int pred = w.stackPred;
  172. // 工作队列置为静止 && 需要唤醒信号
  173. w.source = DORMANT; // enable signal
  174. for (int steps = 0;;) {
  175. int md, rc; long c;
  176. if (w.phase >= 0) {
  177. w.source = 0;
  178. break;
  179. }
  180. // 2)线程池正在停止,则当前工作者需要退出
  181. else if ((md = mode) < 0) {
  182. return;
  183. // 3)线程池正在关闭,则当前工作者需要退出
  184. } else if ((rc = (md & SMASK) + // possibly quiescent
  185. (int)((c = ctl) >> RC_SHIFT)) <= 0 &&
  186. (md & SHUTDOWN) != 0 &&
  187. tryTerminate(false, false)) {
  188. return; // help terminate
  189. // 4)在多次阻塞之间清空中断状态
  190. } else if ((++steps & 1) == 0) {
  191. Thread.interrupted(); // clear between parks
  192. /**
  193. * 5)当前已经无活跃工作者线程 &&
  194. * 已经有工作队列静止 &&
  195. * 当前队列是最近静止的工作队列
  196. */
  197. } else if (rc <= 0 && pred != 0 && phase == (int)c) {
  198. // 计算截止时间
  199. final long d = keepAlive + System.currentTimeMillis();
  200. // 阻塞到截止时间
  201. LockSupport.parkUntil(this, d);
  202. // 阻塞过程中一直无任务提交
  203. if (ctl == c &&
  204. d - System.currentTimeMillis() <= TIMEOUT_SLOP) {
  205. // 递减总工作者线程数
  206. final long nc = UC_MASK & c - TC_UNIT |
  207. SP_MASK & pred;
  208. // 更新控制变量
  209. if (CTL.compareAndSet(this, c, nc)) {
  210. // 将工作队列设置为静止状态
  211. w.phase = QUIET;
  212. // 当前工作者退出工作
  213. return; // drop on timeout
  214. }
  215. }
  216. // 6)阻塞当前工作者等待唤醒,ForkJoinPool 保证至少会有一个工作者线程不会退出
  217. } else {
  218. LockSupport.park(this);
  219. }
  220. }
  221. }
  222. }
  223. }
  224. }
  225. /**
  226. * 将工作者线程 wt 注册到当前线程池中
  227. */
  228. final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
  229. UncaughtExceptionHandler handler;
  230. // 设置为守护线程
  231. wt.setDaemon(true);
  232. // 如果存在异常处理器
  233. if ((handler = ueh) != null) {
  234. // 写入异常处理器
  235. wt.setUncaughtExceptionHandler(handler);
  236. }
  237. // 为工作者线程创建一个工作队列
  238. final WorkQueue w = new WorkQueue(this, wt);
  239. int tid = 0; // for thread name
  240. // 线程池是否为 FIFO 模式
  241. final int fifo = mode & FIFO;
  242. // 读取工作者线程名称前缀
  243. final String prefix = workerNamePrefix;
  244. if (prefix != null) {
  245. synchronized (prefix) {
  246. final WorkQueue[] ws = workQueues; int n;
  247. // 计算索引种子
  248. final int s = indexSeed += SEED_INCREMENT;
  249. if (ws != null && (n = ws.length) > 1) {
  250. // 计算掩码
  251. final int m = n - 1;
  252. // 基于索引种子、掩码计算队列 ID
  253. tid = s & m;
  254. // 计算奇数索引值
  255. int i = m & (s << 1 | 1); // odd-numbered indices
  256. // 查找空闲的 slot
  257. for (int probes = n >>> 1;;) { // find empty slot
  258. WorkQueue q;
  259. // 1)当前索引定位的任务队列为 null || 任务队列为静止状态
  260. if ((q = ws[i]) == null || q.phase == QUIET) {
  261. break;
  262. // 2)所有的奇数索引位都已被占用,则需要进行扩容
  263. } else if (--probes == 0) {
  264. i = n | 1; // resize below
  265. break;
  266. // 3)计算下一个奇数索引位
  267. } else {
  268. i = i + 2 & m;
  269. }
  270. }
  271. // 写入工作队列索引、模式等
  272. final int id = i | fifo | s & ~(SMASK | FIFO | DORMANT);
  273. // 写入队列 ID
  274. w.phase = w.id = id; // now publishable
  275. // 如果索引 i 所在的 slot 为空或工作队列为静止状态
  276. if (i < n) {
  277. // 写入工作队列
  278. ws[i] = w;
  279. } else { // expand array
  280. // 执行 WorkQueue 的扩容
  281. final int an = n << 1;
  282. // 双倍扩容
  283. final WorkQueue[] as = new WorkQueue[an];
  284. // 写入工作队列
  285. as[i] = w;
  286. final int am = an - 1;
  287. for (int j = 0; j < n; ++j) {
  288. WorkQueue v; // copy external queue
  289. // 迁移旧 workQueues 中的任务队列
  290. if ((v = ws[j]) != null) {
  291. as[v.id & am & SQMASK] = v;
  292. }
  293. if (++j >= n) {
  294. break;
  295. }
  296. as[j] = ws[j]; // copy worker
  297. }
  298. // 写入 workQueues
  299. workQueues = as;
  300. }
  301. }
  302. }
  303. // 设置工作者线程名称
  304. wt.setName(prefix.concat(Integer.toString(tid)));
  305. }
  306. return w;
  307. }

ForkJoinTask.fork/join/invoke

  • fork:将任务提交到 ForkJoinPool 中异步执行
  1. /**
  2. * 1)如果当前线程是 ForkJoinPool 工作者线程,则将其提交到驻留的工作队列中。
  3. * 2)否则将当前 ForkJoinTask 任务提交到 common 池中
  4. */
  5. public final ForkJoinTask<V> fork() {
  6. Thread t;
  7. if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
  8. ((ForkJoinWorkerThread)t).workQueue.push(this);
  9. } else {
  10. ForkJoinPool.common.externalPush(this);
  11. }
  12. return this;
  13. }
  • join
  1. /**
  2. * 阻塞等待当前 ForkJoinTask 执行完成并返回结果,
  3. * 任务执行过程中可以抛出 RuntimeException 或 Error 异常。
  4. * 任务执行线程可以是当前线程或其他工作者线程。
  5. */
  6. public final V join() {
  7. int s;
  8. // 1)阻塞等待任务执行完成,如果是异常完成,则将抛出 RuntimeException 或 Error。
  9. if (((s = doJoin()) & ABNORMAL) != 0) {
  10. reportException(s);
  11. }
  12. // 2)执行成功则返回原始结果
  13. return getRawResult();
  14. }
  15. private int doJoin() {
  16. int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
  17. /**
  18. * 1)如果任务已经完成,则返回其状态
  19. * 2)如果当前线程是 ForkJoinWorkerThread &&
  20. * 则尝试从驻留工作队列顶部拉取此任务 &&
  21. * 在当前线程中执行此任务 &&
  22. * 执行成功则返回任务状态
  23. * 3)如果当前线程是 ForkJoinWorkerThread,但是拉取任务失败,
  24. * 则表示【目标任务不在顶部、或其他的工作者线程窃取了此任务在执行】,则等待任务完成。
  25. * 4)如果当前线程不是 ForkJoinWorkerThread,则阻塞等待任务完成。
  26. */
  27. return (s = status) < 0 ? s :
  28. (t = Thread.currentThread()) instanceof ForkJoinWorkerThread ?
  29. (w = (wt = (ForkJoinWorkerThread)t).workQueue).
  30. tryUnpush(this) && (s = doExec()) < 0 ? s :
  31. wt.pool.awaitJoin(w, this, 0L) :
  32. externalAwaitDone();
  33. }
  34. ForkJoinPool#WorkQueue#
  35. /**
  36. * 只有当目标任务 task 是工作队列顶部的第一个任务时,才将此任务移除,并返回 true,
  37. * 否则返回 false。
  38. */
  39. boolean tryUnpush(ForkJoinTask<?> task) {
  40. // 读取 base
  41. final int b = base;
  42. // 读取 top
  43. int s = top, al; ForkJoinTask<?>[] a;
  44. // 任务数组不为空 && 有任务待处理
  45. if ((a = array) != null && b != s && (al = a.length) > 0) {
  46. // 计算读取索引
  47. final int index = al - 1 & --s;
  48. // 如果顶部任务就是当前任务 task,则将 slot 置为 null
  49. if (QA.compareAndSet(a, index, task, null)) {
  50. // 更新 top 值,并返回 true
  51. top = s;
  52. VarHandle.releaseFence();
  53. return true;
  54. }
  55. }
  56. return false;
  57. }
  58. /**
  59. * 窃取任务的主要执行方法
  60. */
  61. final int doExec() {
  62. int s; boolean completed;
  63. // 任务未完成
  64. if ((s = status) >= 0) {
  65. try {
  66. // 立即执行任务
  67. completed = exec();
  68. } catch (final Throwable rex) {
  69. completed = false;
  70. // 设置异常状态
  71. s = setExceptionalCompletion(rex);
  72. }
  73. // 如果正常完成
  74. if (completed) {
  75. // 设置完成状态
  76. s = setDone();
  77. }
  78. }
  79. return s;
  80. }
  81. /**
  82. * 记录异常信息,触发 internalPropagateException 钩子函数
  83. */
  84. private int setExceptionalCompletion(Throwable ex) {
  85. final int s = recordExceptionalCompletion(ex);
  86. if ((s & THROWN) != 0) {
  87. internalPropagateException(ex);
  88. }
  89. return s;
  90. }
  91. final int recordExceptionalCompletion(Throwable ex) {
  92. int s;
  93. // 任务未完成
  94. if ((s = status) >= 0) {
  95. // 计算此 ForkJoinTask 的哈希值
  96. final int h = System.identityHashCode(this);
  97. // 读取异常表的锁
  98. final ReentrantLock lock = exceptionTableLock;
  99. lock.lock();
  100. try {
  101. expungeStaleExceptions();
  102. // 读取异常表
  103. final ExceptionNode[] t = exceptionTable;
  104. // 计算索引
  105. final int i = h & t.length - 1;
  106. // 遍历单向链表
  107. for (ExceptionNode e = t[i]; ; e = e.next) {
  108. /**
  109. * 1)目标 slot 为 null
  110. * 2)已经到达链表尾部
  111. */
  112. if (e == null) {
  113. // 则将此异常加入异常表
  114. t[i] = new ExceptionNode(this, ex, t[i],
  115. exceptionTableRefQueue);
  116. break;
  117. }
  118. // 如果已经加入了,则直接退出
  119. if (e.get() == this) {
  120. break;
  121. }
  122. }
  123. } finally {
  124. lock.unlock();
  125. }
  126. // 设置任务状态
  127. s = abnormalCompletion(DONE | ABNORMAL | THROWN);
  128. }
  129. return s;
  130. }
  131. /**
  132. * 尝试将当前 ForkJoinTask 标记为由于取消或异常而完成
  133. */
  134. private int abnormalCompletion(int completion) {
  135. for (int s, ns;;) {
  136. // 任务已经完成,则返回
  137. if ((s = status) < 0) {
  138. return s;
  139. // 更新任务状态
  140. } else if (STATUS.weakCompareAndSet(this, s, ns = s | completion)) {
  141. // 如果有线程阻塞依赖该任务完成,则唤醒所有的阻塞线程
  142. if ((s & SIGNAL) != 0) {
  143. synchronized (this) { notifyAll(); }
  144. }
  145. return ns;
  146. }
  147. }
  148. }
  149. /**
  150. * 将任务状态设置为 DONE,如果有其他线程在阻塞等待该任务完成,则唤醒所有阻塞的线程
  151. */
  152. private int setDone() {
  153. int s;
  154. /**
  155. * 1)将任务状态设置为 DONE
  156. * 2)如果有其他线程在阻塞等待该任务完成,则唤醒所有阻塞的线程
  157. */
  158. if (((s = (int)STATUS.getAndBitwiseOr(this, DONE)) & SIGNAL) != 0) {
  159. synchronized (this) { notifyAll(); }
  160. }
  161. return s | DONE;
  162. }
  163. ForkJoinPool#WorkQueue#
  164. /**
  165. * 从工作队列的 top 位置开始循环扫描目标任务 task,如果找到则将其移除并执行
  166. */
  167. void tryRemoveAndExec(ForkJoinTask<?> task) {
  168. ForkJoinTask<?>[] wa; int s, wal;
  169. // 此工作队列中有任务待处理
  170. if (base - (s = top) < 0 && // traverse from top
  171. (wa = array) != null && (wal = wa.length) > 0) {
  172. // 从工作队列的 top 位置开始循环扫描目标任务 task,如果找到则将其移除并执行
  173. for (int m = wal - 1, ns = s - 1, i = ns; ; --i) {
  174. final int index = i & m;
  175. final ForkJoinTask<?> t = (ForkJoinTask<?>)
  176. QA.get(wa, index);
  177. // 1)已经没有更多的任务待扫描
  178. if (t == null) {
  179. break;
  180. // 2)当前任务就是目标任务 task
  181. } else if (t == task) {
  182. // 移除该任务
  183. if (QA.compareAndSet(wa, index, t, null)) {
  184. top = ns; // 将已扫描的任务集体下移一个位置
  185. for (int j = i; j != ns; ++j) {
  186. ForkJoinTask<?> f;
  187. final int pindex = j + 1 & m;
  188. f = (ForkJoinTask<?>)QA.get(wa, pindex);
  189. QA.setVolatile(wa, pindex, null);
  190. final int jindex = j & m;
  191. QA.setRelease(wa, jindex, f);
  192. }
  193. VarHandle.releaseFence();
  194. // 执行目标任务
  195. t.doExec();
  196. }
  197. break;
  198. }
  199. }
  200. }
  201. }
  202. final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
  203. int s = 0;
  204. /**
  205. * 工作队列不为 null && 任务不为 null
  206. * 1)task 不是 CountedCompleter 任务
  207. * 2)task 是 CountedCompleter,则尝试窃取和执行目标计算中的任务,直到其完成或无法找到任务为止
  208. */
  209. if (w != null && task != null &&
  210. (!(task instanceof CountedCompleter) ||
  211. (s = w.localHelpCC((CountedCompleter<?>)task, 0)) >= 0)) {
  212. // 尝试从工作队列中移除并运行此任务
  213. w.tryRemoveAndExec(task);
  214. // 读取上次窃取的任务队列ID和当前队列的ID
  215. final int src = w.source, id = w.id;
  216. // 读取任务状态
  217. s = task.status;
  218. // 任务未完成
  219. while (s >= 0) {
  220. WorkQueue[] ws;
  221. boolean nonempty = false;
  222. // 获取随机奇数索引
  223. final int r = ThreadLocalRandom.nextSecondarySeed() | 1; // odd indices
  224. if ((ws = workQueues) != null) { // scan for matching id
  225. for (int n = ws.length, m = n - 1, j = -n; j < n; j += 2) {
  226. WorkQueue q; int i, b, al; ForkJoinTask<?>[] a;
  227. /**
  228. * 目标索引 i 定位到的工作队列不为 null &&
  229. * 此工作队列最近窃取了当前工作队列的任务 &&
  230. * 此工作队列有任务待处理 &&
  231. * 则帮助其处理任务
  232. */
  233. if ((i = r + j & m) >= 0 && i < n &&
  234. (q = ws[i]) != null && q.source == id &&
  235. (b = q.base) - q.top < 0 &&
  236. (a = q.array) != null && (al = a.length) > 0) {
  237. // 窃取任务的队列ID
  238. final int qid = q.id;
  239. // 从 base 位置开始窃取
  240. final int index = al - 1 & b;
  241. // 读取任务
  242. final ForkJoinTask<?> t = (ForkJoinTask<?>)
  243. QA.getAcquire(a, index);
  244. /**
  245. * 目标任务不为 null &&
  246. * 没有其他队列并发窃取此任务 &&
  247. * 则尝试将此任务从目标工作队列中移除
  248. */
  249. if (t != null && b++ == q.base && id == q.source &&
  250. QA.compareAndSet(a, index, t, null)) {
  251. // 窃取成功,则更新 base 值
  252. q.base = b;
  253. // 记录最近窃取任务的任务队列 ID
  254. w.source = qid;
  255. // 执行目标任务
  256. t.doExec();
  257. // 回写上次窃取任务的队列ID
  258. w.source = src;
  259. }
  260. nonempty = true;
  261. // 窃取并处理完一个任务,则退出循环
  262. break;
  263. }
  264. }
  265. }
  266. // 1)目标任务已经完成,则返回
  267. if ((s = task.status) < 0) {
  268. break;
  269. // 2)一个任务都没有窃取到
  270. } else if (!nonempty) {
  271. long ms, ns; int block;
  272. // 1)非超时模式
  273. if (deadline == 0L) {
  274. ms = 0L; // untimed
  275. // 2)如果已经超时,则返回
  276. } else if ((ns = deadline - System.nanoTime()) <= 0L) {
  277. break; // timeout
  278. // 3)未超时,但是剩余时间 < 1 毫秒,则将其设置为 1 毫秒
  279. } else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
  280. {
  281. ms = 1L; // avoid 0 for timed wait
  282. }
  283. // 尝试增加一个补偿工作者来处理任务
  284. if ((block = tryCompensate(w)) != 0) {
  285. // 阻塞等待
  286. task.internalWait(ms);
  287. // 如果添加成功,则递增活跃工作者数
  288. CTL.getAndAdd(this, block > 0 ? RC_UNIT : 0L);
  289. }
  290. s = task.status;
  291. }
  292. }
  293. }
  294. return s;
  295. }
  296. /**
  297. * 如果任务未完成,则阻塞等待
  298. */
  299. final void internalWait(long timeout) {
  300. /**
  301. * 将(旧 status 值 | SIGNAL) 的值写入 status 中,并返回旧值
  302. * 如果任务未完成
  303. */
  304. if ((int)STATUS.getAndBitwiseOr(this, SIGNAL) >= 0) {
  305. synchronized (this) {
  306. // 1)如果任务未完成,则阻塞等待
  307. if (status >= 0) {
  308. try { wait(timeout); } catch (final InterruptedException ie) { }
  309. // 2)如果任务已经完成,则唤醒阻塞在此任务上的所有线程
  310. } else {
  311. notifyAll();
  312. }
  313. }
  314. }
  315. }
  316. /**
  317. * 阻塞一个非工作者线程,直到任务完成
  318. */
  319. private int externalAwaitDone() {
  320. int s = tryExternalHelp();
  321. // 任务未完成 && 写入唤醒标记
  322. if (s >= 0 && (s = (int)STATUS.getAndBitwiseOr(this, SIGNAL)) >= 0) {
  323. boolean interrupted = false;
  324. synchronized (this) {
  325. for (;;) {
  326. // 1)任务未完成
  327. if ((s = status) >= 0) {
  328. try {
  329. // 阻塞等待任务完成
  330. wait(0L);
  331. // 工作者线程被中断,可能是线程池终止
  332. } catch (final InterruptedException ie) {
  333. interrupted = true;
  334. }
  335. }
  336. // 2)任务完成则唤醒在此任务上阻塞等待的线程
  337. else {
  338. notifyAll();
  339. break;
  340. }
  341. }
  342. }
  343. // 工作者线程被设置了中断标记
  344. if (interrupted) {
  345. // 则中断此工作者线程
  346. Thread.currentThread().interrupt();
  347. }
  348. }
  349. // 返回任务状态
  350. return s;
  351. }
  352. private int tryExternalHelp() {
  353. int s;
  354. /**
  355. * 1)当前任务已经完成,则返回其状态
  356. * 2)任务未完成,此任务是 CountedCompleter,则执行 externalHelpComplete
  357. * 3)任务未完成,此任务是 ForkJoinTask,则执行 tryExternalUnpush && 拉取任务成功,则执行它
  358. */
  359. return (s = status) < 0 ? s:
  360. this instanceof CountedCompleter ?
  361. ForkJoinPool.common.externalHelpComplete(
  362. (CountedCompleter<?>)this, 0) :
  363. ForkJoinPool.common.tryExternalUnpush(this) ?
  364. doExec() : 0;
  365. }
  366. final boolean tryExternalUnpush(ForkJoinTask<?> task) {
  367. // 读取线程测试值
  368. final int r = ThreadLocalRandom.getProbe();
  369. WorkQueue[] ws; WorkQueue w; int n;
  370. // 定位到的共享队列不为 null,则尝试从目标共享队列中移除此任务
  371. return (ws = workQueues) != null &&
  372. (n = ws.length) > 0 &&
  373. (w = ws[n - 1 & r & SQMASK]) != null &&
  374. w.trySharedUnpush(task);
  375. }
  376. ForkJoinPool#WorkQueue
  377. boolean trySharedUnpush(ForkJoinTask<?> task) {
  378. boolean popped = false;
  379. final int s = top - 1;
  380. int al; ForkJoinTask<?>[] a;
  381. // 任务数组不为空
  382. if ((a = array) != null && (al = a.length) > 0) {
  383. // 计算目标索引
  384. final int index = al - 1 & s;
  385. // 读取任务
  386. final ForkJoinTask<?> t = (ForkJoinTask<?>) QA.get(a, index);
  387. // 读取的任务就是目标任务 task && 尝试锁定共享队列
  388. if (t == task &&
  389. PHASE.compareAndSet(this, 0, QLOCK)) {
  390. // 锁定成功 && 确认没有出现竞争 && 将目标 slot 置为 null
  391. if (top == s + 1 && array == a &&
  392. QA.compareAndSet(a, index, task, null)) {
  393. // 成功弹出任务
  394. popped = true;
  395. // 更新 top 值
  396. top = s;
  397. }
  398. // 释放共享锁
  399. PHASE.setRelease(this, 0);
  400. }
  401. }
  402. return popped;
  403. }
  • invoke
  1. /**
  2. * 立即在当前线程中执行此任务,等待任务执行完毕并返回结果,
  3. * 或抛出 RuntimeException 或 Error 异常。
  4. */
  5. public final V invoke() {
  6. int s;
  7. if (((s = doInvoke()) & ABNORMAL) != 0) {
  8. reportException(s);
  9. }
  10. return getRawResult();
  11. }
  12. private int doInvoke() {
  13. int s; Thread t; ForkJoinWorkerThread wt;
  14. return (s = doExec()) < 0 ? s :
  15. (t = Thread.currentThread()) instanceof ForkJoinWorkerThread ?
  16. (wt = (ForkJoinWorkerThread)t).pool.
  17. awaitJoin(wt.workQueue, this, 0L) :
  18. externalAwaitDone();
  19. }

ForkJoinPool 源码分析的更多相关文章

  1. ForkJoinPool源码简单解析

    ForkJoin框架之ForkJoinTask  java  阅读约 62 分钟 前言 在前面的文章"CompletableFuture和响应式编程"中提到了ForkJoinTas ...

  2. 多线程高并发编程(8) -- Fork/Join源码分析

    一.概念 Fork/Join就是将一个大任务分解(fork)成许多个独立的小任务,然后多线程并行去处理这些小任务,每个小任务处理完得到结果再进行合并(join)得到最终的结果. 流程:任务继承Recu ...

  3. 源码分析:Phaser 之更灵活的同步屏障

    简介 Phaser 是 JDK 1.7 开始提供的一个可重复使用的同步屏障,功能类似于CyclicBarrier和CountDownLatch,但使用更灵活,支持对任务的动态调整,并支持分层结构来达到 ...

  4. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  5. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  6. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  7. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  8. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  9. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

随机推荐

  1. SpringDataJPA第三天讲义

    第1章     Specifications动态查询 有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecif ...

  2. Image Processing and Analysis_15_Image Registration: A Method for Registration of 3-D shapes——1992

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  3. json —— pickle 的序列化和反序列化

    前言json的序列化和反序列化 1, json 只能序列化简单的数据类型,如,列表,字典,字符串,等简单的类型,不能序列化复杂的类型. 2, json 是支持所有的语言的,多以我们跨语言的时候都是用j ...

  4. Codeforces Round #590 (Div. 3) 万恶的自己WAC

    C题:一道简单的C题卡了半天,我太菜了 题意:给你一个n*2的矩阵,每个位置有一个数字,对应一种管道,要求通道可不可以从左上通到右下 由提议可以看出,1,2对应的是直管道,3,4,5,6对应弯管道,只 ...

  5. LoadRunner生成测试报告

     loadrunner笔记(三):设置.运行场景和生成测试报告   //上一篇的代码有点问题,问题出在 web_reg_find()函数中,这个函数简单的说是搜索下一步操作的请求对象(html)页面中 ...

  6. javascript逻辑非(!/!!)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 牛客小白月赛11 Rinne Loves Xor

    题目链接:https://ac.nowcoder.com/acm/contest/370/I code: #include<bits/stdc++.h> using namespace s ...

  8. 外网可以反问lxr

    , 'baseurl_aliases' => 174       [ 'http://172.168.2.4/lxr' 175       , 'http://mydomain/lxr' 176 ...

  9. Day1 读题解题提升

    The 2014 ACM-ICPC Asia Mudanjiang Regional Contest 昨晚做了训练赛,然后读题又自闭了QAQ. Average Score ZOJ - 3819 题意: ...

  10. Density of Power Network(ZOJ 3708)

    Problem The vast power system is the most complicated man-made system and the greatest engineering i ...