Fork/Join框架的实现原理

ForkJoinPool由ForkJoinTask数组和ForkJoinWorkerThread数组组成,ForkJoinTask数组负责

将存放程序提交给ForkJoinPool的任务,而ForkJoinWorkerThread数组负责执行这些任务。

(1)ForkJoinTask的fork方法实现原理

当我们调用ForkJoinTask的fork方法时,程序会调用ForkJoinWorkerThread的pushTask方法

异步地执行这个任务,然后立即返回结果。代码如下。

public final ForkJoinTask<V> fork() {
    ((ForkJoinWorkerThread) Thread.currentThread())
    .pushTask(this);
    return this;
}

pushTask方法把当前任务存放在ForkJoinTask数组队列里。然后再调用ForkJoinPool的

signalWork()方法唤醒或创建一个工作线程来执行任务。代码如下。

final void pushTask(ForkJoinTask<> t) {
    ForkJoinTask<>[] q; int s, m;
    if ((q = queue) != null) {    // ignore if queue removed
    long u = (((s = queueTop) & (m = q.length - 1)) << ASHIFT) + ABASE;
    UNSAFE.putOrderedObject(q, u, t);
    queueTop = s + 1;      // or use putOrderedInt
    if ((s -= queueBase) <= 2)
    pool.signalWork();
    else if (s == m)
    growQueue();
    }
}

(2)ForkJoinTask的join方法实现原理

Join方法的主要作用是阻塞当前线程并等待获取结果。让我们一起看看ForkJoinTask的join

方法的实现,代码如下。

public final V join() {
    if (doJoin() != NORMAL)
    return reportResult();
    else
    return getRawResult();
    }
    private V reportResult() {
    int s; Throwable ex;
    if ((s = status) == CANCELLED)
    throw new CancellationException();
    if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
    UNSAFE.throwException(ex);
    return getRawResult();
}

首先,它调用了doJoin()方法,通过doJoin()方法得到当前任务的状态来判断返回什么结

果,任务状态有4种:已完成(NORMAL)、被取消(CANCELLED)、信号(SIGNAL)和出现异常

(EXCEPTIONAL)。

·如果任务状态是已完成,则直接返回任务结果。

·如果任务状态是被取消,则直接抛出CancellationException。

·如果任务状态是抛出异常,则直接抛出对应的异常。

让我们再来分析一下doJoin()方法的实现代码。

private int doJoin() {
    Thread t; ForkJoinWorkerThread w; int s; boolean completed;
    if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
    if ((s = status) < 0)
    return s;
    if ((w = (ForkJoinWorkerThread)t).unpushTask(this)) {
    try {
    completed = exec();
    } catch (Throwable rex) {
    return setExceptionalCompletion(rex);
    }
    if (completed)
    return setCompletion(NORMAL);
    }
    return w.joinTask(this);
    }
    else
    return externalAwaitDone();
}

在doJoin()方法里,首先通过查看任务的状态,看任务是否已经执行完成,如果执行完成,

则直接返回任务状态;如果没有执行完,则从任务数组里取出任务并执行。如果任务顺利执行

完成,则设置任务状态为NORMAL,如果出现异常,则记录异常,并将任务状态设置为

EXCEPTIONAL。

Last updated