H__D  

一、Fork/Join 基本介绍和使用

  参考:【Java多线程】 Fork/Join框架(三十)

二、线程池结构 及 调用图

1、线程池结构图

  

2、线程池调用图

    

3、线程池ctl属性变化图

  


4、WorkQueue的scanState属性变化图

  

三、示例代码

 1 public class CountTask extends RecursiveTask<Integer> {
 2     // 阀值
 3     private static final int THRESHOLD = 2;
 4     private int start;
 5     private int end;
 6 
 7     public CountTask(int start, int end) {
 8         this.start = start;
 9         this.end = end;
10     }
11 
12     @Override
13     protected Integer compute() {
14         int sum = 0;
15 
16         try {
17             // 让计算慢一点
18             Thread.sleep(1000);
19         } catch (InterruptedException e) {
20             e.printStackTrace();
21         }
22 
23         // 如果任务足够小就计算任务
24         boolean canCompute = (end - start) <= THRESHOLD;
25         if(canCompute) {
26             for (int i = start; i <= end; i++) {
27                 sum += i;
28             }
29         }else {
30             // 如果任务大于阀值,就分裂成两个子任务计算
31             int middle = (start + end) / 2;
32 
33             CountTask leftTask = new CountTask(start, middle);
34             CountTask rightTask = new CountTask(middle + 1, end);
35             // 执行子任务
36             leftTask.fork();
37             rightTask.fork();
38 
39             // 等待子任务执行完,并得到器结果
40             int leftResult = leftTask.join();
41             int rightResult = rightTask.join();
42             // 合并子任务
43             sum = leftResult + rightResult;
44         }
45         // 可以观察任务,是那个线程执行的
46         System.out.println(Thread.currentThread().getName() + "-> start = " + start + ", end = " + end);
47         return sum;
48     }
49 
50     public static void main(String[] args) throws InterruptedException {
51         ForkJoinPool forkJoinPool = new ForkJoinPool(2);
52         // 生产一个计算任务,负责计算 1+2+3+4
53         CountTask task = new CountTask(1, 100);
54 //        // 使用公共的线程
55 //        ForkJoinTask<Integer> result = task.fork();
56         // 方案一:使用自定义的线程池,执行一个任务
57         Future<Integer> result = forkJoinPool.submit(task);
58 
59         new Thread(() -> {
60             while (true) {
61                 try {
62                     Thread.sleep(500);
63                 } catch (InterruptedException e) {
64                     e.printStackTrace();
65                 }
66                 // 跟踪线程池状态 toString() 方法
67                 System.out.println(forkJoinPool.toString());
68             }
69         }).start();
70         try {
71             // 打印结果
72             System.out.println(result.get());
73         } catch (ExecutionException e) {
74             e.printStackTrace();
75         }
76 
77 //        // 方案二:使用invoke,相当于外部提交任务 + join内部任务
78 //        Integer result = forkJoinPool.invoke(task);
79 //        System.out.println(result);
80 
81         // 方案三:execute,提交任务,当是没有返回值
82 //        forkJoinPool.execute(task);
83 
84     }
85 }

四、源码分析主要属性

1、ForkJoinPool属性

 1 public class ForkJoinPool extends AbstractExecutorService {
 2 
 3     // 限定参数
 4     static final int SMASK = 0xffff; // 低位掩码,也是最大索引位 对应16个1(1_111_111_111_111_111)
 5     static final int MAX_CAP = 0x7fff; // 工作线程最大容量    对应15个1(111_111_111_111_111)
 6     static final int EVENMASK = 0xfffe; // 偶数低位掩码 对应(1_111_111_111_111_110)
 7     static final int SQMASK = 0x007e; // workQueues 数组最多64个槽位 (1_111_110)
 8 
 9     // ctl 子域和 WorkQueue.scanState 的掩码和标志位
10     static final int SCANNING = 1; // 标记是否正在运行任务 
11     static final int INACTIVE = 1 << 31; // 失活状态 负数 
12     static final int SS_SEQ = 1 << 16; // 版本戳,防止ABA问题
13 
14     // ForkJoinPool.config 和 WorkQueue.config 的配置信息标记 
15     static final int MODE_MASK = 0xffff << 16; // 模式掩码 
16     static final int LIFO_QUEUE = 0; //LIFO队列
17     static final int FIFO_QUEUE = 1 << 16;//FIFO队列
18     static final int SHARED_QUEUE = 1 << 31; // 共享模式队列,负数
19 
20     // 种子生成器的增量。
21     private static final int SEED_INCREMENT = 0x9e3779b9;
22 
23     // Lower and upper word masks
24     private static final long SP_MASK    = 0xffffffffL;
25     private static final long UC_MASK    = ~SP_MASK;
26 
27     // Active counts
28     private static final int  AC_SHIFT   = 48;
29     private static final long AC_UNIT    = 0x0001L << AC_SHIFT;
30     private static final long AC_MASK    = 0xffffL << AC_SHIFT;
31 
32     // Total counts
33     private static final int  TC_SHIFT   = 32;
34     private static final long TC_UNIT    = 0x0001L << TC_SHIFT;
35     private static final long TC_MASK    = 0xffffL << TC_SHIFT;
36     private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign
37 
38 
39 
40     // 线程池运行状态
41     private static final int RSLOCK = 1;        // 已锁    1 -> 0
42     private static final int RSIGNAL = 1 << 1;     // 2 -> 10
43     private static final int STARTED = 1 << 2;    // 启动    4 -> 100
44     private static final int STOP = 1 << 29;    // 
45     private static final int TERMINATED = 1 << 30;    // 
46     private static final int SHUTDOWN = 1 << 31;    //
47 
48     // 线程池控制标识
49     // 二进制0~31位: SP(StackPred)区,sp=(int)ctl,SP区不等于0,表示有工作线程workerF在休眠,
50     // 二进制0~15位:保存了WorkQueue[]的下标
51     // 二进制16~31位:WorkQueue状态,第一位表示active(0)或者inactive(1),其余十五位表示版本好(对付ABA)
52     // 二进制32~47位:TC(total count)区,总工作线程数减去目标并行度(parallelism),中高16位。如果是负数,说明总线程数不够。
53     //                当总工作线程数 小于 parallelism时,TC就会为负数
54     // 二进制48~63位:AC(active count)区,正在运行工作线程数减去目标并行度(parallelism),高16位。如果是负数,说明活跃工作线程数不够
55     //                 当运行工作线程数 小于 parallelism时,AC就会为负数
56     volatile long ctl;                   // main pool control
57     // 运行状态
58     // 负数是shutdown,其余都是2的次方
59     volatile int runState;               // lockable status
60     // 配置
61     // 配置:二进制的低16位代表 并行度(parallelism)
62     //         二进制的高16位代表:mode可选FIFO_QUEUE(1 << 16)和LIFO_QUEUE(1 << 31),默认是LIFO_QUEUE
63     final int config;                    // parallelism, mode
64     // 生成worker的queue索引
65     int indexSeed;                       // to generate worker index
66     // 工作队列数组
67     volatile WorkQueue[] workQueues;     // main registry
68     // 线程工厂
69     final ForkJoinWorkerThreadFactory factory;
70     // 未捕获异常处理
71     final UncaughtExceptionHandler ueh;  // per-worker UEH
72     // worker名字前缀
73     final String workerNamePrefix;       // to create worker name string
74     // 窃取计数器
75     volatile AtomicLong stealCounter;    // also used as sync monitor
76 
77     ......
78 }

2、WorkQueue属性

 1 static final class WorkQueue {
 2 
 3     // 初始化队列容量
 4     static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
 5 
 6     // 队列最大容量
 7     static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
 8 
 9     // Instance fields
10     // 负数:inactive, 非负数:active, 其中奇数代表scanning,偶数代表正在执行任务
11     volatile int scanState;    // versioned, <0: inactive; odd:scanning
12     // sp = (int)ctl, 前一个队列栈的标示信息,包含版本号、是否激活、以及队列索引  
13     int StackPred;             // pool stack (ctl) predecessor
14     // 窃取的任务数
15     int nsteals;               // number of steals
16     // 一个随机数,用来帮助任务窃取,在 helpXXXX()的方法中会用到
17     int hint;                  // randomization and stealer index hint
18     // 配置:二进制的低16位代表 在 queue[] 中的索引,
19     // 高16位:mode可选FIFO_QUEUE(1 << 16)和LIFO_QUEUE(1 << 31),默认是LIFO_QUEUE
20     int config;                // pool index and mode
21     // 锁定标示位:1: locked, < 0: terminate; else 0
22     volatile int qlock;        // 1: locked, < 0: terminate; else 0
23     // 尾标
24     volatile int base;         // index of next slot for poll
25     // 头标
26     int top;                   // index of next slot for push
27     // 任务列表
28     ForkJoinTask<?>[] array;   // the elements (initially unallocated)
29     // 包含的线程池
30     final ForkJoinPool pool;   // the containing pool (may be null)
31     // 拥有的ForkJoinWorkerThread线程
32     final ForkJoinWorkerThread owner; // owning thread or null if shared
33     // worker等待线程,在等待时间就是owner自己线程
34     volatile Thread parker;    // == owner during call to park; else null
35     // 当前join 任务
36     volatile ForkJoinTask<?> currentJoin;  // task being joined in awaitJoin
37     volatile ForkJoinTask<?> currentSteal; // mainly used by helpStealer
38 
39     // 工作队列
40     WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
41         // 线程池
42         this.pool = pool;
43         // 拥有者
44         this.owner = owner;
45         // 将索引放置在数组的中心,初始为4096
46         base = top = INITIAL_QUEUE_CAPACITY >>> 1;
47     }
48 
49     ....
50 }

3、ForkJoinTask属性

 1 public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
 2 
 3     // 任务运行状态
 4     volatile int status; // accessed directly by pool and workers
 5     // 完成标识
 6     static final int DONE_MASK   = 0xf0000000;  // mask out non-completion bits
 7     // 正常完成
 8     static final int NORMAL      = 0xf0000000;  // must be negative
 9     // 取消
10     static final int CANCELLED   = 0xc0000000;  // must be < NORMAL
11     // 异常
12     static final int EXCEPTIONAL = 0x80000000;  // must be < CANCELLED
13     // 等待信息
14     static final int SIGNAL      = 0x00010000;  // must be >= 1 << 16
15     // 标记
16     static final int SMASK       = 0x0000ffff;  // short bits for tags
17 
18 
19     ....
20 }

五、源码分析主要方法

  以下方法,默认都是在 ForkJoinPool 类中

1、线程池ForkJoinPool构造方法

 1 // 默认创建 ForkJoinPool 线程池
 2 public ForkJoinPool() {
 3     this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
 4          defaultForkJoinWorkerThreadFactory, null, false);
 5 }
 6 
 7 
 8 public ForkJoinPool(int parallelism) {
 9     this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
10 }
11 
12 // 参数:
13 // parallelism:并行级别。 对于默认值,请使用Runtime.availableProcessors()
14 // factory:创建新线程的工厂。 默认值为defaultForkJoinWorkerThreadFactory 。
15 // handler:由于执行任务时遇到不可恢复的错误而终止的内部工作线程的处理程序。 默认值为null 。
16 // asyncMode:工作队列模式,false为后进显出,true为先进先出
17 
18 public ForkJoinPool(int parallelism,
19                     ForkJoinWorkerThreadFactory factory,
20                     UncaughtExceptionHandler handler,
21                     boolean asyncMode) {
22     this(checkParallelism(parallelism),
23          checkFactory(factory),
24          handler,
25          asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
26          "ForkJoinPool-" + nextPoolId() + "-worker-");
27     checkPermission();
28 }
29 
30 // mode 模式:0为后进显出,65536为先进先出
31 // workerNamePrefix:woker线程名前缀
32 private ForkJoinPool(int parallelism,
33                      ForkJoinWorkerThreadFactory factory,
34                      UncaughtExceptionHandler handler,
35                      int mode,
36                      String workerNamePrefix) {
37     this.workerNamePrefix = workerNamePrefix;
38     this.factory = factory;
39     this.ueh = handler;
40     this.config = (parallelism & SMASK) | mode;
41     long np = (long)(-parallelism); // offset ctl counts
42     // ctl 二进制高47-63位是AC(active counts)区
43     // ctl 
44     this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
45 }

2、submit() 和 externalPush() 方法

 1 // 提交任务
 2 public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
 3     if (task == null)
 4         throw new NullPointerException();
 5 
 6     // 外部推送任务
 7     externalPush(task);
 8     return task;
 9 }
10 
11 
12 
13 // 外部推送任务
14 final void externalPush(ForkJoinTask<?> task) {
15     WorkQueue[] ws; WorkQueue q; int m;
16 
17     // 获取当前线程 threadLocalRandomProbe 偏移量
18     int r = ThreadLocalRandom.getProbe();
19     // 运行状态rs
20     int rs = runState;
21 
22     // 如果工作队列不为空,且工作队列长度大于0                       (ws = workQueues) != null && (m = (ws.length - 1)) >= 0
23     // q = ws[m & r & SQMASK],q为ws中随机的偶数索引。
24     // SQMASK为0x007e 126二进制位为11111110所以q的结果永远为偶数
25     // U.compareAndSwapInt(q, QLOCK, 0, 1)加锁,QLOCK为第q个WorkQueue对象的锁的引用
26     if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
27         (q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 &&
28         U.compareAndSwapInt(q, QLOCK, 0, 1)) {
29         ForkJoinTask<?>[] a; int am, n, s;
30         if ((a = q.array) != null &&
31             (am = a.length - 1) > (n = (s = q.top) - q.base)) {
32             // j:偏移量,即是top对应的数组位置偏移量
33             int j = ((am & s) << ASHIFT) + ABASE;
34             // 把任务放入WorkQueue[q].array[s]中
35             U.putOrderedObject(a, j, task);
36             // 队列的top++;
37             U.putOrderedInt(q, QTOP, s + 1);
38             // 解锁
39             U.putIntVolatile(q, QLOCK, 0);
40             // 处于active的工作线程不够则新建work来
41             if (n <= 1)
42                 signalWork(ws, q);
43             return;
44         }
45         // 解锁队列工作组
46         U.compareAndSwapInt(q, QLOCK, 1, 0);
47     }
48 
49     // 外部提交任务
50     externalSubmit(task);
51 }
View Code

3、externalSubmit() 方法

  1 // 外部提交任务
  2 private void externalSubmit(ForkJoinTask<?> task) {
  3     // 取得一个随机探查数,可能为0也可能为其它数
  4     int r;                                    // initialize caller's probe
  5     if ((r = ThreadLocalRandom.getProbe()) == 0) {
  6         ThreadLocalRandom.localInit();
  7         r = ThreadLocalRandom.getProbe();
  8     }
  9     // 循环退出条件 任务提交成功
 10     for (;;) {
 11         WorkQueue[] ws; WorkQueue q; int rs, m, k;
 12         boolean move = false;
 13 
 14         // 运行状态是否小于0
 15         if ((rs = runState) < 0) {
 16             tryTerminate(false, false);     // help terminate
 17             throw new RejectedExecutionException();
 18         }
 19 
 20         // 由于所有状态值都是 1 >> 几位
 21         // 那么下面判断 (rs & STARTED) == 0 的意思是 rs != STARTED
 22         // 没初始化,就初始化工作队列组WorkQueue[]
 23         else if ((rs & STARTED) == 0 ||     // initialize
 24                  ((ws = workQueues) == null || (m = ws.length - 1) < 0)) {
 25             int ns = 0;
 26 
 27             // 运行状态rs加锁,锁标志位低位置为1
 28             rs = lockRunState();
 29             try {
 30                 // 没初始化,则新建一个WorkQueue
 31                 if ((rs & STARTED) == 0) {
 32 
 33                     // stealCounter窃取计数器,初始化
 34                     U.compareAndSwapObject(this, STEALCOUNTER, null,
 35                                            new AtomicLong());
 36 
 37                     // 创建一个size为2的n次方的WorkQueue数组
 38                     // 确保至少有2个槽
 39                     int p = config & SMASK; // ensure at least 2 slots
 40 
 41                     int n = (p > 1) ? p - 1 : 1;
 42                     n |= n >>> 1; n |= n >>> 2;  n |= n >>> 4;
 43                     n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
 44                     // 计算得到数组长度
 45                     // 初始化WorkQueue数组
 46                     workQueues = new WorkQueue[n];
 47 
 48                     // 设置运行状态rs:STARTED:4 -> 100
 49                     ns = STARTED;
 50                 }
 51             } finally {
 52                 // 运行状态rs解锁,并设置新的运行状态
 53                 unlockRunState(rs, (rs & ~RSLOCK) | ns);
 54             }
 55         }
 56 
 57         // 线程对应的工作队列不为空
 58         // k 对应的值一定是偶数,应为m为奇数,SQMASK为偶数,与操作之后一定为奇数
 59         else if ((q = ws[k = r & m & SQMASK]) != null) {
 60             // q.qlock ->  1: 锁定,<0:终止;否则0
 61             // 工作队列q-CAS加锁
 62             if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
 63                 // 任务列表
 64                 ForkJoinTask<?>[] a = q.array;
 65                 // 队列头
 66                 int s = q.top;
 67                 boolean submitted = false; // initial submission or resizing
 68                 try {                      // locked version of push
 69                     if ((a != null && a.length > s + 1 - q.base) ||
 70                         (a = q.growArray()) != null) {
 71 
 72                         // 数组对象内存布局:对象头(MarkWord + 对象指针 + 数组长度) + 实际数据 + 对其填充
 73                         // j为偏移量,ABASE 对象头长度 + (((a.length - 1) & s) << ASHIFT 引用占4个字节) 实际数据偏移
 74                         // 偏移量,即是top对应的数组位置偏移量
 75                         int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
 76 
 77                         // putOrderedObject方法在指定的对象a中,指定的内存偏移量的位置,赋予一个新的元素
 78                         U.putOrderedObject(a, j, task);
 79 
 80                         // putOrderedInt方法对当前指定的对象中的指定字段,进行赋值操作
 81                         // 这里的代码意义是将workQueue对象本身中的top标示的位置 + 1,
 82                         U.putOrderedInt(q, QTOP, s + 1);
 83                         
 84                         // 提交任务完成标识
 85                         submitted = true;
 86                     }
 87                 } finally {
 88                     // 工作队列q-CAS解锁
 89                     U.compareAndSwapInt(q, QLOCK, 1, 0);
 90                 }
 91                 if (submitted) {
 92                     // 尝试激活队列q中的线程或创建工作线程
 93                     signalWork(ws, q);
 94                     return;
 95                 }
 96             }
 97             move = true;                   // move on failure
 98         }
 99         // 运行状态 != RSLOCK
100         else if (((rs = runState) & RSLOCK) == 0) { // create new queue
101             // 创建一个工作队列
102             q = new WorkQueue(this, null);
103             // 随机化和偷窃指数提示
104             q.hint = r;
105             // 池索引和模式
106             q.config = k | SHARED_QUEUE;
107             // 扫描状态:0:不活动;奇数:扫描
108             // INACTIVE,非活动
109             q.scanState = INACTIVE;
110             // 运行状态rs加锁,返回状态值5
111             rs = lockRunState();           // publish index
112             // 队列不为空
113             if (rs > 0 &&  (ws = workQueues) != null &&
114                 k < ws.length && ws[k] == null)
115                 // 将工作队列放入工作队列组中
116                 ws[k] = q;                 // else terminated
117             // 运行状态rs解锁
118             unlockRunState(rs, rs & ~RSLOCK);
119         }
120         else
121             move = true;                   // move if busy
122         if (move)
123             // 重新获取线程特有的 Probe 偏移量
124             r = ThreadLocalRandom.advanceProbe(r);
125     }
126 }
View Code

4、growArray() 方法

 1 // 初始化,或者扩容任务列表
 2 final ForkJoinTask<?>[] growArray() {
 3     ForkJoinTask<?>[] oldA = array;
 4     // 任务数组大小 扩容2倍 ,最小值8192
 5     int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
 6     // 最大值 67108864
 7     if (size > MAXIMUM_QUEUE_CAPACITY)
 8         throw new RejectedExecutionException("Queue capacity exceeded");
 9 
10     int oldMask, t, b;
11     ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
12     // 有数据情况,迁移数据
13     if (oldA != null && (oldMask = oldA.length - 1) >= 0 &&
14         (t = top) - (b = base) > 0) {
15         int mask = size - 1;    
16         do { // emulate poll from old array, push to new array
17             ForkJoinTask<?> x;
18             // 计算新旧对象的偏移量
19             int oldj = ((b & oldMask) << ASHIFT) + ABASE;
20             int j    = ((b &    mask) << ASHIFT) + ABASE;
21             x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj);
22             if (x != null &&
23                 U.compareAndSwapObject(oldA, oldj, x, null))
24                 U.putObjectVolatile(a, j, x);
25         } while (++b != t);
26     }
27     return a;
28 }
View Code

5、lockRunState() 和 unlockRunState() 方法

 1 // 运行状态(runState)加锁,返回状态值1
 2 private int lockRunState() {
 3     int rs;
 4     // RSLOCK = 1
 5     // (rs = runState) & RSLOCK 结果要么是1 要么是0
 6     // 1代表已锁,0没有锁
 7     return ((((rs = runState) & RSLOCK) != 0 ||
 8             // 修改运行状态(runState)为 1
 9              !U.compareAndSwapInt(this, RUNSTATE, rs, rs |= RSLOCK)) ?
10             //  等待获取运行状态锁
11             awaitRunStateLock() : rs);
12 }
13 
14 
15 // 运行状态(runState)解锁,无返回值
16 private void unlockRunState(int oldRunState, int newRunState) {
17     // 修改运行状态(runState)为 newRunState
18     if (!U.compareAndSwapInt(this, RUNSTATE, oldRunState, newRunState)) {
19         // 解锁失败,进入
20         // 获取stealCounter窃取计数器
21         Object lock = stealCounter;
22         // 给属性runState赋值新状态
23         runState = newRunState;              // clears RSIGNAL bit
24         if (lock != null)
25             // 唤醒其他线程
26             synchronized (lock) { lock.notifyAll(); }
27     }
28 }
View Code

6、signalWork() 、 tryAddWorker() 和 createWorker() 方法

 1 final void signalWork(WorkQueue[] ws, WorkQueue q) {
 2     long c; int sp, i; WorkQueue v; Thread p;
 3     // 判断ctl是否小于0,即判断对应的AC区。运行线程是否饱和
 4     while ((c = ctl) < 0L) {                       // too few active
 5         // (int)ctl : 获取ctl的低32位区
 6         // sp:第一位是0,没有版本号,没有inactive的worker
 7         if ((sp = (int)c) == 0) {                  // no idle workers
 8             // tc: tc不为0,就是代表 total worker - parallelism < 0, 所以需要添加worker
 9             // sp 判断了ctl低32位区都 0,在判断TC区
10             if ((c & ADD_WORKER) != 0L)            // too few workers
11                 tryAddWorker(c);
12             break;
13         }
14         if (ws == null)                            // unstarted/terminated
15             break;
16         // 取栈顶的worker,如果下标已经越界或queue为null,线程池都是终止了
17         // i为worker的下标
18         if (ws.length <= (i = sp & SMASK))         // terminated
19             break;
20         // v 就是休眠的worker线程
21         if ((v = ws[i]) == null)                   // terminating
22             break;
23         // 新的scanState,版本+1,设置状态为激活,INACTIVE = 1 << 31,~INACTIVE = 01111111....
24         int vs = (sp + SS_SEQ) & ~INACTIVE;        // next scanState
25         // 确认 worker的 sp没有变化
26         int d = sp - v.scanState;                  // screen CAS
27         // 生成新的 ctl,(UC_MASK & (c + AC_UNIT))设置 高32位, (SP_MASK & v.stackPred)设置低32位
28         long nc = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & v.stackPred);
29         if (d == 0 && U.compareAndSwapLong(this, CTL, c, nc)) {
30             // 激活worker,设置版本+1的scanState
31             v.scanState = vs;                      // activate v
32             if ((p = v.parker) != null)
33                 U.unpark(p);
34             break;
35         }
36         //当前queue没有task 需要执行了,则停止signal
37         if (q != null && q.base == q.top)          // no more work
38             break;
39     }
40 }
41 
42 
43 // 添加worker
44 private void tryAddWorker(long c) {
45     boolean add = false;
46     do {
47         // nc 是ctl的 AC区+1 与TC区+1 的数据结果
48         long nc = ((AC_MASK & (c + AC_UNIT)) |
49                    (TC_MASK & (c + TC_UNIT)));
50 
51         if (ctl == c) {
52             int rs, stop;                 // check if terminating
53             // 运行状态rs加锁,运行状态不等于STOP,CAS修改线程池运行状态rs
54             if ((stop = (rs = lockRunState()) & STOP) == 0)
55                 // CAS修改 ctl的 AC区+1 与TC区+1 的数据,相当于工作线程+1
56                 add = U.compareAndSwapLong(this, CTL, c, nc);
57             // 运行状态rs解锁
58             unlockRunState(rs, rs & ~RSLOCK);
59             if (stop != 0)
60                 break;
61             if (add) {
62                 // 创建工作线程
63                 createWorker();
64                 break;
65             }
66         }
67     } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
68 }
69 
70 // 创建工作线程
71 private boolean createWorker() {
72     ForkJoinWorkerThreadFactory fac = factory;
73     Throwable ex = null;
74     ForkJoinWorkerThread wt = null;
75     try {
76         // 线程工厂,创建线程,this就是线程池本身对象
77         if (fac != null && (wt = fac.newThread(this)) != null) {
78             wt.start();
79             return true;
80         }
81     } catch (Throwable rex) {
82         ex = rex;
83     }
84     // 撤销worker
85     deregisterWorker(wt, ex);
86     return false;
87 }
View Code

7、newThread() 、 ForkJoinWorkerThread() 和 registerWorker() 方法

 1 // DefaultForkJoinWorkerThreadFactory 类中的 newThread()
 2 // 创建ForkJoinWorkerThread类线程
 3 public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
 4     return new ForkJoinWorkerThread(pool);
 5 }
 6 
 7 // 构造方法
 8 protected ForkJoinWorkerThread(ForkJoinPool pool) {
 9     // Use a placeholder until a useful name can be set in registerWorker
10     super("aForkJoinWorkerThread");
11     this.pool = pool;
12 
13     // 调用线程池的注册工作线程方法,this就是线程本身
14     this.workQueue = pool.registerWorker(this);
15 }
16 
17 
18 final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
19     UncaughtExceptionHandler handler;
20     // 设置为守护线程
21     wt.setDaemon(true);                           // configure thread
22     // 异常handler是否为空
23     if ((handler = ueh) != null)
24         wt.setUncaughtExceptionHandler(handler);
25     // 创建一个工作队列
26     WorkQueue w = new WorkQueue(this, wt);
27     int i = 0;                                    // assign a pool index
28     // 取config第16位
29     // 高16位:mode可选FIFO_QUEUE(1 << 16)和LIFO_QUEUE(1 << 31),默认是LIFO_QUEUE
30     int mode = config & MODE_MASK;
31     // 线程池运行状态rs加锁
32     int rs = lockRunState();
33     try {
34         WorkQueue[] ws; int n;                    // skip if no array
35         // 工作队列组不为空
36         if ((ws = workQueues) != null && (n = ws.length) > 0) {
37             // 起始位置 + 种子增长量
38             int s = indexSeed += SEED_INCREMENT;  // unlikely to collide
39             int m = n - 1;
40             // worker的queue肯定放在pool中的queue[]中的奇数下标
41             // m = ws.lenght - 1, ws.lenght 肯定是偶数,则m 肯定是奇数
42             // 1的二进制位:00000001, 所以任何数 "|" 1 都是奇数
43             // 所以 奇数 & 奇数 , 1&1 = 1,所以i肯定是奇数
44             i = ((s << 1) | 1) & m;               // odd-numbered indices
45             // 判断工作队列组对应位置是否为空
46             if (ws[i] != null) {                  // collision
47                 int probes = 0;                   // step by approx half n
48                 // 计算一个步长
49                 // 如果下标已经有队列,则重新生成奇数下标
50                 // step肯定为偶数:EVENMASK:0xfffe:1111111111111110
51                 // 所以 奇数+偶数,奇偶性不变
52                 int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
53                 // 已步长位单位,在工作队列组找到 为空的槽
54                 while (ws[i = (i + step) & m] != null) {
55                     if (++probes >= n) {
56                         // 找了n次后,还未找到,对workQueues复制扩容,扩容成2倍原大小
57                         workQueues = ws = Arrays.copyOf(ws, n <<= 1);
58                         m = n - 1;
59                         probes = 0;
60                     }
61                 }
62             }
63             // 
64             w.hint = s;                           // use as random seed
65             // 配置:二进制的低16位代表 在 queue[] 中的索引
66             w.config = i | mode;
67             // 扫描状态
68             w.scanState = i;                      // publication fence
69             // 将新建的WorkQueue放到工作队列组中
70             ws[i] = w;
71         }
72     } finally {
73         // 运行状态rs解锁
74         unlockRunState(rs, rs & ~RSLOCK);
75     }
76     // 设置线程名,i 是queue[]中的奇数下标,那么i >>> 1,就是下标除以2
77     wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
78     return w;
79 }
View Code 

8、run() 、 runWorker() 和 scan() 方法

  ForkJoinWorkerThread 的 run() 方法

  1 // ForkJoinWorkerThread 的 run() 方法
  2 public void run() {
  3 
  4     if (workQueue.array == null) { // only run once
  5         Throwable exception = null;
  6         try {
  7             // 钩子方法 onStart()
  8             onStart();
  9             // 线程池调用runWorker()方法
 10             pool.runWorker(workQueue);
 11         } catch (Throwable ex) {
 12             exception = ex;
 13         } finally {
 14             try {
 15                 // 钩子方法,处理异常
 16                 onTermination(exception);
 17             } catch (Throwable ex) {
 18                 if (exception == null)
 19                     exception = ex;
 20             } finally {
 21                 // 注销线程
 22                 pool.deregisterWorker(this, exception);
 23             }
 24         }
 25     }
 26 }
 27 
 28 // ForkJoinPool 类中
 29 final void runWorker(WorkQueue w) {
 30     // 初始化
 31     w.growArray();                   // allocate queue
 32     int seed = w.hint;               // initially holds randomization hint
 33     int r = (seed == 0) ? 1 : seed;  // avoid 0 for xorShift
 34     for (ForkJoinTask<?> t;;) {
 35         if ((t = scan(w, r)) != null)
 36             w.runTask(t);
 37         else if (!awaitWork(w, r))
 38             break;
 39         r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
 40     }
 41 }
 42 
 43 
 44 
 45 
 46 
 47 // 扫描任务
 48 private ForkJoinTask<?> scan(WorkQueue w, int r) {
 49     WorkQueue[] ws; int m;
 50     if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && w != null) {
 51         int ss = w.scanState;                     // initially non-negative
 52         // k = r & m 。 r是一个随机数,m 是 队列数组长度 - 1;用于定位去哪个 队列 窃取 task
 53         for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
 54             WorkQueue q; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
 55             int b, n; long c;
 56                    
 57             if ((q = ws[k]) != null) {
 58                 // 如果有还没执行的task,尝试窃取队列q 中的base下标的 task。 即FIFO
 59                 // i: 在内存中,b下标对应的对象的偏移值。 a.length - 1 的二进制位 永远是 0[1...]s,所以 (a.length - 1) & b = b,主要是保证了b不会越界
 60                 if ((n = (b = q.base) - q.top) < 0 &&
 61                     (a = q.array) != null) {      // non-empty
 62                     // 偏移量,即是b对应的数组位置偏移量
 63                     long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
 64                     if ((t = ((ForkJoinTask<?>)
 65                               U.getObjectVolatile(a, i))) != null &&
 66                         q.base == b) {
 67                         // ss 是小偷的 scanState,大于0代表当前的worker是激活的
 68                         if (ss >= 0) {
 69                             // 把 task 从 队列中取出来,然后队列的base+1,如果被窃取的队列中有多于1个的task,则尝试唤醒其他的worker
 70                             if (U.compareAndSwapObject(a, i, t, null)) {
 71                                 q.base = b + 1;
 72                                 if (n < -1)       // signal others
 73                                     signalWork(ws, q);
 74                                 return t;
 75                             }
 76                         }
 77                         // ss小于0代表当前的worker是未激活的,并且当前是第一次扫描,这时候尝试激活worker
 78                         // oldSum: 上一次遍历周期的 base 值的和。
 79                         // (int) c : 可以拿到当前栈顶的空闲worker。sp = (int) c
 80                         else if (oldSum == 0 &&   // try to activate
 81                                  w.scanState < 0)
 82                             tryRelease(c = ctl, ws[m & (int)c], AC_UNIT);
 83                     }
 84 
 85                     if (ss < 0)                   // refresh
 86                         ss = w.scanState;
 87                     // 更新随机值,重新初始化所有控制变量,重新定位队列
 88                     r ^= r << 1; r ^= r >>> 3; r ^= r << 10;
 89                     origin = k = r & m;           // move and rescan
 90                     oldSum = checkSum = 0;
 91                     continue;
 92                 }
 93                 checkSum += b;
 94             }
 95             // 每次没有窃取到task的时候,都会k+1(k值不会超过m),
 96             // 当k遍历了一圈还没有steal到任务,则当前小偷worker是过剩的,则inactive这个小偷worker
 97             if ((k = (k + 1) & m) == origin) {    // continue until stable
 98 
 99                 // oldSum == (oldSum = checkSum) 实际上就是 oldSum == checkSum , oldSum = checkSum
100                 // oldSum == checkSum 是判断 这个周期和上个周期 的base和是否一直,如果一直, 说明base可能没有变过
101                 if ((ss >= 0 || (ss == (ss = w.scanState))) &&
102                     oldSum == (oldSum = checkSum)) {
103                     if (ss < 0 || w.qlock < 0)    // already inactive
104                         break;
105                     // ns 保存了前一个队列栈的标示信息,包含版本号、是否激活、以及队列索引 
106                     // 对一个worker的描述,包括队列位置下标,线程是否激活,版本好
107                     int ns = ss | INACTIVE;       // try to inactivate
108                     // 把ns的信息放到 ctl 中的前36位
109                     long nc = ((SP_MASK & ns) |
110                                (UC_MASK & ((c = ctl) - AC_UNIT)));
111                     // w对象stackPred栈的标示信息,保持上次一次ctl中保存的work栈信息
112                     w.stackPred = (int)c;         // hold prev stack top
113                     // 设置w的scanState字段,保证队列栈信息
114                     U.putInt(w, QSCANSTATE, ns);
115                     // CAS修改ctl
116                     if (U.compareAndSwapLong(this, CTL, c, nc))
117                         ss = ns;
118                     else
119                         // 修改失败,scanState改回来
120                         w.scanState = ss;         // back out
121                 }
122                 checkSum = 0;
123             }
124         }
125     }
126     return null;
127 }
View Code

9、runTask() 、doExec() 、exec()和 setCompletion() 方法

  ForkJoinTask 类中的 doExec()

  ForkJoinTask 实现类中的 exec()

  ForkJoinTask 类中的 setCompletion()

 1 final void runTask(ForkJoinTask<?> task) {
 2     if (task != null) {
 3         // 扫描状态
 4         scanState &= ~SCANNING; // mark as busy
 5         // 被盗任务的主要执行方法
 6         (currentSteal = task).doExec();
 7         // 将当前窃取任务currentSteal属性置空
 8         U.putOrderedObject(this, QCURRENTSTEAL, null); // release for GC
 9         execLocalTasks();
10         ForkJoinWorkerThread thread = owner;
11         // 窃取数量+1
12         if (++nsteals < 0)      // collect on overflow
13             transferStealCount(pool);
14         scanState |= SCANNING;
15         if (thread != null)
16             // 钩子方法
17             thread.afterTopLevelExec();
18     }
19 }
20 
21 
22 
23 // ForkJoinTask 类中的 doExec()
24 // 被盗任务的主要执行方法
25 final int doExec() {
26     int s; boolean completed;
27     // 判断任务状态,是否未结束
28     if ((s = status) >= 0) {
29         try {
30             // 调用exec()方法
31             completed = exec();
32         } catch (Throwable rex) {
33             return setExceptionalCompletion(rex);
34         }
35         if (completed)
36             // 设置正常完成状态
37             s = setCompletion(NORMAL);
38     }
39     return s;
40 }
41 
42 // ForkJoinTask 实现类类中的 doExec()
43 // RecursiveTask exec()
44 protected final boolean exec() {
45     // 执行自定义类 实现的 compute() 方法
46     // 且设置结果
47     result = compute();
48     return true;
49 }
50 
51 // ForkJoinTask 类中的 setCompletion()
52 // 设置完成
53 private int setCompletion(int completion) {
54     for (int s;;) {
55         // 任务 < 0 ,已结束状态
56         if ((s = status) < 0)
57             return s;
58         // CAS 设置任务状态是 completion:one of NORMAL, CANCELLED, EXCEPTIONAL
59         if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
60             // 任务之前是等待信号状态,即其他线程设置了信号,通知其唤醒其他线程
61             if ((s >>> 16) != 0)
62                 synchronized (this) { notifyAll(); }
63             return completion;
64         }
65     }
66 }
View Code

10、awaitWork() 方法

 1 // 等待任务
 2 private boolean awaitWork(WorkQueue w, int r) {
 3     //qlock值的含义:1: locked, < 0: terminate; else 0,所以这里小于0表示终止
 4     if (w == null || w.qlock < 0)                 // w is terminating
 5         return false;
 6     for (int pred = w.stackPred, spins = SPINS, ss;;) {
 7         //表示worker被重新激活了,跳出循环返回true
 8         if ((ss = w.scanState) >= 0)
 9             break;
10         //空转,当前SPINS值为0,表示不空转。空转表示执行的代码啥也不敢,就是拖拖时间,看空转期间相关的状态是否
11         else if (spins > 0) {
12             r ^= r << 6; r ^= r >>> 21; r ^= r << 7;
13             if (r >= 0 && --spins == 0) {         // randomize spins
14                 WorkQueue v; WorkQueue[] ws; int s, j; AtomicLong sc;
15                 if (pred != 0 && (ws = workQueues) != null &&
16                     (j = pred & SMASK) < ws.length &&
17                     (v = ws[j]) != null &&        // see if pred parking
18                     (v.parker == null || v.scanState >= 0))
19                     spins = SPINS;                // continue spinning
20             }
21         }
22         else if (w.qlock < 0)                     // recheck after spins
23             return false;
24         // 判断线程是否被中断
25         else if (!Thread.interrupted()) {
26             long c, prevctl, parkTime, deadline;
27             // ac的值 
28             // (config & SMASK) = 并行度(parallelism) + ctl中AC区的值
29             int ac = (int)((c = ctl) >> AC_SHIFT) + (config & SMASK);
30             //这里由于采用了非阻塞策略,所以tryTerminate中调用Thread.interrupt并不会让当前线程
31             // 活跃工作线程为0,尝试终止线程池
32             if ((ac <= 0 && tryTerminate(false, false)) ||
33                 (runState & STOP) != 0)           // pool terminating
34                 return false;
35             //当前没有活跃worker,且当前worker处于worker等待栈的顶部
36             if (ac <= 0 && ss == (int)c) {        // is last waiter
37                 // prevctl:高32位UC区活动工作线程+1 组合 低32位区的worker栈信息
38                 prevctl = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & pred);
39                 // t = 总线程数-并行度的值
40                 int t = (short)(c >>> TC_SHIFT);  // shrink excess spares
41                 //因为当前已经没有活跃线程了,这意味着任务已经执行完毕,且没有调用pool的shutdown关闭
42                 //pool,所以留下一部分线程,这样当有新任务来时,可以复用这些线程。但是留下的线程也不能太多
43                 //毕竟目前已经没有要处理的任务了。t>2表示已经预留了足够多的线程了,而使用CAS则是因为CTL有可能
44                 //被其他线程更改,为何还会有其他线程更改呢?有这几种情况,1是因为其他线程在执行tryTerminate把
45                 //自己设置为未激活状态,从而让自己处于worker等待栈的顶部,而当前worker则不再处于worker等待栈
46                 //的顶部,栈中元素得一个一个出才行,不能出栈任意位置的元素,否则会有线程安全问题。另外则是可能
47                 //“来活了”,即有新任务来了,所以有线程被激活或有新线程被创建。所以必须满足下面if的两个条件才能
48                 //终止当前worker
49                 if (t > 2 && U.compareAndSwapLong(this, CTL, c, prevctl))
50                     return false;                 // else use timed wait
51                 parkTime = IDLE_TIMEOUT * ((t >= 0) ? 1 : 1 - t);
52                 // 休眠时间 
53                 deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
54             }
55             else
56                 prevctl = parkTime = deadline = 0L;
57             Thread wt = Thread.currentThread();
58             U.putObject(wt, PARKBLOCKER, this);   // emulate LockSupport
59             w.parker = wt;
60             if (w.scanState < 0 && ctl == c)      // recheck before park
61                 U.park(false, parkTime);
62             //如果线程等待了一段时间发现还没有任务要执行,则终止自己,否则线程自动醒来执行任务
63             U.putOrderedObject(w, QPARKER, null);
64             U.putObject(wt, PARKBLOCKER, null);
65             if (w.scanState >= 0)
66                 break;
67             if (parkTime != 0L && ctl == c &&
68                 deadline - System.nanoTime() <= 0L &&
69                 // 休眠结束,活跃线程加1,ctl改变此线程休眠前的状态
70                 U.compareAndSwapLong(this, CTL, c, prevctl))
71                 return false;                     // shrink pool
72         }
73     }
74     return true;
75 }
View Code

11、deregisterWorker() 方法

 1 // 注销工作线程
 2 final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
 3     WorkQueue w = null;
 4     if (wt != null && (w = wt.workQueue) != null) {
 5         WorkQueue[] ws;                           // remove index from array
 6         // idex :为config低16位保存的,在队列组中索引下标位置
 7         int idx = w.config & SMASK;
 8         // 线程池运行状态加锁
 9         int rs = lockRunState();
10         if ((ws = workQueues) != null && ws.length > idx && ws[idx] == w)
11             // 从队列中移除worker
12             ws[idx] = null;
13         // 线程池运行状态解锁
14         unlockRunState(rs, rs & ~RSLOCK);
15     }
16     long c;                                       // decrement counts
17     // 修改ctl,AC区与TC区 线程数-1
18     do {} while (!U.compareAndSwapLong
19                  (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
20                                        (TC_MASK & (c - TC_UNIT)) |
21                                        (SP_MASK & c))));
22     if (w != null) {
23         w.qlock = -1;                             // ensure set
24         // 窃取任务数,汇总到线程池stealCounter上
25         w.transferStealCount(this);
26         // 删除和取消所有已知任务,忽略任何异常。
27         w.cancelAll();                            // cancel remaining tasks
28     }
29     for (;;) {                                    // possibly replace
30         WorkQueue[] ws; int m, sp;
31         if (tryTerminate(false, false) || w == null || w.array == null ||
32             (runState & STOP) != 0 || (ws = workQueues) == null ||
33             (m = ws.length - 1) < 0)              // already terminating
34             break;
35         // 判断是否存在休眠worker线程,存在去释放
36         if ((sp = (int)(c = ctl)) != 0) {         // wake up replacement
37             // 尝试唤醒休眠的worker或创建worker
38             if (tryRelease(c, ws[sp & m], AC_UNIT))
39                 break;
40         }
41         else if (ex != null && (c & ADD_WORKER) != 0L) {
42             tryAddWorker(c);                      // create replacement
43             break;
44         }
45         else                                      // don't need replacement
46             break;
47     }
48     if (ex == null)                               // help clean on way out
49         ForkJoinTask.helpExpungeStaleExceptions();
50     else                                          // rethrow
51         ForkJoinTask.rethrow(ex);
52 }
View Code

12、tryRelease() 方法

 1 // 释放worker
 2 private boolean tryRelease(long c, WorkQueue v, long inc) {
 3     // sp 一个worker栈的标示信息
 4     // vs worker栈的标示信息:版本+1,并设为激活状态
 5     int sp = (int)c, vs = (sp + SS_SEQ) & ~INACTIVE; Thread p;
 6     // 确认scanState 没有被改动
 7     if (v != null && v.scanState == sp) {          // v is at top of stack
 8         // nc:ctl 的 sp还原到上一次状态,且ac区+inc
 9         long nc = (UC_MASK & (c + inc)) | (SP_MASK & v.stackPred);
10         if (U.compareAndSwapLong(this, CTL, c, nc)) {
11             v.scanState = vs;
12             if ((p = v.parker) != null)
13                 // 唤醒worker线程
14                 U.unpark(p);
15             return true;
16         }
17     }
18     return false;
19 }
View Code

13、fork() 和 push() 方法

  ForkJoinTask 类中的 fork()

  WorkQueue 类中的 push()

 1 // ForkJoinTask 类中的 fork()
 2 public final ForkJoinTask<V> fork() {
 3     Thread t;()) 
 4     // 判断线程是否为 ForkJoinWorkerThread 内部线程 
 5     if ((t = Thread.currentThreadinstanceof ForkJoinWorkerThread)
 6         // 调用push方法 将任务放入当前线程的工作队列
 7         ((ForkJoinWorkerThread)t).workQueue.push(this);
 8     else
 9         // 在静态代码块中,有调用makeCommonPool()方法,创建了公共的ForkJoinPool线程池 commonPool
10         // 将任务放到公共的ForkJoinPool线程池线程池中
11         ForkJoinPool.common.externalPush(this);
12     return this;
13 }
14 
15 
16 // WorkQueue 类中的 push()
17 final void push(ForkJoinTask<?> task) {
18     ForkJoinTask<?>[] a; ForkJoinPool p;
19     int b = base, s = top, n;
20     if ((a = array) != null) {    // ignore if queue removed
21         int m = a.length - 1;     // fenced write for task visibility
22         // 根据偏移量,将任务放入工作队列中,即队列top指向的位置
23         U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
24         // top+1
25         U.putOrderedInt(this, QTOP, s + 1);
26         // 判断任务是否小于等于1,
27         // 如果是且线程池不为空,尝试激活此工作队列中的线程或创建工作线程
28         if ((n = s - b) <= 1) {
29             if ((p = pool) != null)
30                 // 尝试激活此工作队列中的线程或创建工作线程
31                 p.signalWork(p.workQueues, this);
32         }
33         else if (n >= m)
34             growArray();
35     }
36 }
View Code

14、join() 、 doJoin() 、tryUnpush() 和 getRawResult() 方法

  ForkJoinTask 类中的 join()

  ForkJoinTask 类中的 doJoin()

  ForkJoinTask 类实现类中的 getRawResult()

 1 // ForkJoinTask 类中的 join()
 2 public final V join() {
 3     int s;
 4     // 执行doJoin()方法,如果doJoin返回的是非NORMAL,报告异常
 5     if ((s = doJoin() & DONE_MASK) != NORMAL)
 6         reportException(s);
 7     // 获取结果获取结果
 8     return getRawResult();
 9 }
10 
11 
12 
13 // ForkJoinTask 类中的 doJoin()
14 // 执行join
15 // status表示任务执行状态,有如下值:
16 // static final int NORMAL      = 0xf0000000;  // 已完成 < 0
17 // static final int CANCELLED   = 0xc0000000;  // 被取消 < NORMAL
18 // static final int EXCEPTIONAL = 0x80000000;  // 必须 < CANCELLED
19 // static final int SIGNAL      = 0x00010000;  // 信号 >= 1 << 16
20 //所以status<0表示任务已经完成,或取消,或抛异常,无论怎样,就是任务结束了
21 //下面这段代码的意思是,任务是否结束,是则返回,否则看任务执行线程是否是ForkJoinWorkerThread实例
22 //否则externalAwaitDone()等待,是则尝试让任务出队并执行,如果不能出队或者执行无法完成,则使用
23 // wt.pool.awaitJoin(w, this, 0L)等待。externalAwaitDone()基本就是wait和notify,而awaitJoin
24 //就复杂点,需要帮助窃取当前任务的worker(称为stealer)尽快执行任务,即会窃取stealer的任务来执行
25 private int doJoin() {
26     int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
27     // 判断任务状态,是否未结束
28     return (s = status) < 0 ? s :
29 
30         ((t = ForkJoinWorkerThreadad.currentThread()) instanceof ForkJoinWorkerThread) ?
31 
32         (w = (wt = (ForkJoinWorkerThread)t).workQueue).
33         // 尝试将this任务移出工作队列,并且    使用当前线程执行
34         tryUnpush(this) && (s = doExec()) < 0 ? s :
35         // 等待join任务完成
36         wt.pool.awaitJoin(w, this, 0L) 
37 
38         // 外部等待完成任务
39         : externalAwaitDone();
40 }
41 
42 
43 // 尝试将t任务移出工作队列
44 final boolean tryUnpush(ForkJoinTask<?> t) {
45     ForkJoinTask<?>[] a; int s;
46     if ((a = array) != null && (s = top) != base &&
47         // 根据偏移量,将top指向的位置,置空
48         U.compareAndSwapObject
49         (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
50         // top下移一位
51         U.putOrderedInt(this, QTOP, s);
52         return true;
53     }
54     return false;
55 }
56 
57 
58 // ForkJoinTask 类实现类中的 doJoin()
59 // 返回结果
60 public final V getRawResult() {
61     return result;
62 }
View Code

15、awaitJoin() 和 internalWait() 方法

  ForkJoinTask 类实现类中的 internalWait()

 1 // 等待join
 2 final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
 3     int s = 0;
 4     if (task != null && w != null) {
 5         // currentJoin这个属性基本仅在这个方法内使用,这里先把currentJoin保存在prevJoin
 6         // 而把当前任务引用赋予currentJoin,所以这里可以看出,任务之间必须是有向无环图,比如任务A和B
 7         // 不能A等待B完成,然后B又等待A完成,这样会造成死锁。不过真遇到这种情况,也有解决方法,就是
 8         // 设置等待超时时间,所以下面的wait即internalWait的等待是有超时时间的
 9         ForkJoinTask<?> prevJoin = w.currentJoin;
10         // 将任务锁定到当前任务
11         U.putOrderedObject(w, QCURRENTJOIN, task);
12         // 如果任务属于CountedCompleter 类型任务,则进行强转
13         CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
14             (CountedCompleter<?>)task : null;
15         for (;;) {
16             if ((s = task.status) < 0)
17                 break;
18             if (cc != null)
19                 helpComplete(w, cc, 0);
20             // 如果当前工作队列没有任务,且task未完成,则task被人窃取了
21             // tryRemoveAndExec 尝试移除和执行
22             else if (w.base == w.top || w.tryRemoveAndExec(task))
23             //帮助stealer执行任务,毕竟当前自身队列的任务已经执行完了,所以帮助stealer执行任务, 
24             //以尽快能够返回
25                 helpStealer(w, task);
26             if ((s = task.status) < 0)
27                 break;
28             long ms, ns;
29             if (deadline == 0L)
30                 ms = 0L;
31             else if ((ns = deadline - System.nanoTime()) <= 0L)
32                 break;
33             else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
34                 ms = 1L;
35             //尝试增加一个线程作为补偿,因为当前线程准备进入等待,能到达这里,表示
36             //任务未完成,且工作队列还有任务
37             // 效果增加额外的线程(非核心线程)来处理任务,ctl的AC不变,TC会+1
38             if (tryCompensate(w)) {
39                 // 内部等待,任务完成
40                 task.internalWait(ms);
41                 // CAS修改,ctl的AC区数据 + 1,即活跃线程数+1
42                 U.getAndAddLong(this, CTL, AC_UNIT);
43             }
44         }
45         U.putOrderedObject(w, QCURRENTJOIN, prevJoin);
46     }
47     return s;
48 }
49 
50 
51 // ForkJoinTask 类实现类中的 internalWait()
52 // 内部等待
53 final void internalWait(long timeout) {
54     int s;
55     if ((s = status) >= 0 && // force completer to issue notify
56         // 标记任务,即给一个信号给任务,任务完成,唤醒此线程
57         U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
58         // 锁定任务,然后进行等待
59         synchronized (this) {
60             if (status >= 0)
61                 try { wait(timeout); } catch (InterruptedException ie) { }
62             else
63                 notifyAll();
64         }
65     }
66 }
View Code

16、externalAwaitDone() 方法

 1 // ForkJoinTask 类中的 externalAwaitDone()
 2 // 外部等待完成
 3 private int externalAwaitDone() {
 4 
 5     int s = ((this instanceof CountedCompleter) ? // try helping
 6              ForkJoinPool.common.externalHelpComplete(
 7                  (CountedCompleter<?>)this, 0) :
 8              // 尝试将任务放入common线程池,然后执行
 9              ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
10     // 如果任务未完成
11     if (s >= 0 && (s = status) >= 0) {
12         boolean interrupted = false;
13         do {
14             // 将状态改为 SIGNAL
15             if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
16                 synchronized (this) {
17                     if (status >= 0) {
18                         try {
19                             // 调用wait() 
20                             wait(0L);
21                         } catch (InterruptedException ie) {
22                             interrupted = true;
23                         }
24                     }
25                     else
26                         notifyAll();
27                 }
28             }
29         } while ((s = status) >= 0);
30         // 如果被中断
31         if (interrupted)
32             Thread.currentThread().interrupt();
33     }
34     return s;
35 }
View Code

17、tryRemoveAndExec() 方法

 1 // WorkQueue 类中的 tryRemoveAndExec()
 2 // 尝试移除任务和执行
 3 final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
 4     ForkJoinTask<?>[] a; int m, s, b, n;
 5     if ((a = array) != null && (m = a.length - 1) >= 0 &&
 6         task != null) {
 7         while ((n = (s = top) - (b = base)) > 0) {
 8             for (ForkJoinTask<?> t;;) {      // traverse from s to b
 9                 // 由于--s,所以j偏移量从top位置往base位置,迭代移动
10                 long j = ((--s & m) << ASHIFT) + ABASE;
11                 if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
12                     return s + 1 == top;     // shorter than expected
13                 else if (t == task) {
14                     boolean removed = false;
15                     if (s + 1 == top) {      // pop
16                         // 如果task是top位置任务,就移除,并返回移除成功
17                         if (U.compareAndSwapObject(a, j, task, null)) {
18                             U.putOrderedInt(this, QTOP, s);
19                             removed = true;
20                         }
21                     }
22                     // 判断base指针没有变化
23                     else if (base == b)      // replace with proxy
24                         // 如果j指向的位置是task任务,则移除task任务,使用空任务代替
25                         removed = U.compareAndSwapObject(
26                             a, j, task, new EmptyTask());
27                     // 移除成功,执行任务
28                     if (removed)
29                         task.doExec();
30                     break;
31                 }
32                 else if (t.status < 0 && s + 1 == top) {
33                     if (U.compareAndSwapObject(a, j, t, null))
34                         U.putOrderedInt(this, QTOP, s);
35                     break;                  // was cancelled
36                 }
37                 // 未找到,表示此任务,不在此队列中,被其他队列窃取了
38                 // 退出返回
39                 if (--n == 0)
40                     return false;
41             }
42             if (task.status < 0)
43                 return false;
44         }
45     }
46     return true;
47 }
View Code

18、tryCompensate() 方法

 1 // 尝试补偿方式
 2 private boolean tryCompensate(WorkQueue w) {
 3     boolean canBlock;
 4     WorkQueue[] ws; long c; int m, pc, sp;
 5     if (w == null || w.qlock < 0 ||           // caller terminating
 6         (ws = workQueues) == null || (m = ws.length - 1) <= 0 ||
 7         (pc = config & SMASK) == 0)           // parallelism disabled
 8         canBlock = false;
 9     else if ((sp = (int)(c = ctl)) != 0)      // release idle worker
10         canBlock = tryRelease(c, ws[sp & m], 0L);
11     else {
12         // ac 运行中的工作线程数
13         int ac = (int)(c >> AC_SHIFT) + pc;
14         // tc 总线程数
15         int tc = (short)(c >> TC_SHIFT) + pc;
16         int nbusy = 0;                        // validate saturation
17         // 遍历工作队列组每一个槽
18         for (int i = 0; i <= m; ++i) {        // two passes of odd indices
19             WorkQueue v;
20             // 下标为奇数的工作队列,即工作worker
21             if ((v = ws[((i << 1) | 1) & m]) != null) {
22                 // 查找非工作状态下的worker,即scanState为非负数中的奇数
23                 if ((v.scanState & SCANNING) != 0)
24                     break;
25                 ++nbusy;
26             }
27         }
28         if (nbusy != (tc << 1) || ctl != c)
29             canBlock = false;                 // unstable or stale
30         else if (tc >= pc && ac > 1 && w.isEmpty()) {
31             long nc = ((AC_MASK & (c - AC_UNIT)) |
32                        (~AC_MASK & c));       // uncompensated
33             canBlock = U.compareAndSwapLong(this, CTL, c, nc);
34         }
35         else if (tc >= MAX_CAP ||
36                  (this == common && tc >= pc + commonMaxSpares))
37             throw new RejectedExecutionException(
38                 "Thread limit exceeded replacing blocked worker");
39         else {                                // similar to tryAddWorker
40             boolean add = false; int rs;      // CAS within lock
41             // tc区数值 + 1
42             long nc = ((AC_MASK & c) |
43                        (TC_MASK & (c + TC_UNIT)));
44             if (((rs = lockRunState()) & STOP) == 0)
45                 // CAS修改ctl,总线程数+1
46                 add = U.compareAndSwapLong(this, CTL, c, nc);
47             unlockRunState(rs, rs & ~RSLOCK);
48             // 创建工作线程
49             canBlock = add && createWorker(); // throws on exception
50         }
51     }
52     return canBlock;
53 }
View Code

六、总结

  1、Fork/Join 框架 提供了一种把大任务分割成若干小任务,最终计算完小任务汇总到大任务的结果框架

  2、Fork/Join 框架 使用了窃取算法,工作队列中自己任务完成后,可以窃取其他工作队列中的任务执行

  3、Fork/Join 通过任务队列,可以获取到,任务发生的异常

  

参考:

  1、《Java并发编程的艺术》

  2、https://blog.csdn.net/u010841296/article/details/83963637

  3、https://blog.csdn.net/tyrroo/article/details/81483608

posted on 2021-04-02 13:22  H__D  阅读(194)  评论(0编辑  收藏  举报