fork-join中有个重要概念叫工作窃取,涉及一个是任务的分拆存放,一个偷。源码:
public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
int s1, s2;
t2.fork();
if (((s1 = t1.doInvoke()) & ABNORMAL) != 0)
t1.reportException(s1);
if (((s2 = t2.doJoin()) & ABNORMAL) != 0)
t2.reportException(s2);
}
t2.fork()把任务工作放到队列,t1接下来执行,doInvoke()。
public final ForkJoinTask<V> fork() {
Thread t;
if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
((ForkJoinWorkerThread)t).workQueue.push(this);
else
ForkJoinPool.common.externalPush(this);
return this;
}
偷取工作任务
private boolean scan(WorkQueue w, int r) {
WorkQueue[] ws; int n;
if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) {
for (int m = n - 1, j = r & m;;) {
WorkQueue q; int b;
if ((q = ws[j]) != null && q.top != (b = q.base)) {
int qid = q.id;
ForkJoinTask<?>[] a; int cap, k; ForkJoinTask<?> t;
if ((a = q.array) != null && (cap = a.length) > 0) {
t = (ForkJoinTask<?>)QA.getAcquire(a, k = (cap - 1) & b);
if (q.base == b++ && t != null &&
QA.compareAndSet(a, k, t, null)) {
q.base = b;
w.source = qid;
if (q.top - b > 0)
signalWork();
w.topLevelExec(t, q, // random fairness bound
r & ((n << TOP_BOUND_SHIFT) - 1));
}
}
return true;
}
else if (--n > 0)
j = (j + 1) & m;
else
break;
}
}
return false;
}