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