Fork/Join框架實現原理

ForkJoinPool由ForkJoinTask數組和ForkJoinWorkerThread數組組成,ForkJoinTask數組負責存放程序提交給ForkJoinPool的任務,而ForkJoinWorkerThread數組負責執行這些任務。

ForkJoinTask的fork方法實現原理。當咱們調用ForkJoinTask的fork方法時,程序會調用ForkJoinWorkerThread的pushTask方法異步的執行這個任務,而後當即返回結果。代碼以下:java

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

pushTask方法把當前任務存放在ForkJoinTask 數組queue裏。而後再調用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();
        }
    }

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()方法獲得當前任務的狀態來判斷返回什麼結果,任務狀態有四種:已完成(NORMAL),被取消(CANCELLED),信號(SIGNAL)和出現異常(EXCEPTIONAL)。this

若是任務狀態是已完成,則直接返回任務結果。
若是任務狀態是被取消,則直接拋出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。code

相關文章
相關標籤/搜索