[Java] Fork/Join compute vs join

以Fibonacci series為例探討Fork/Join的compute和join
![DSC_0788[1].JPG](https://qiita-image-store.s3.amazonaws.com/0/84946/65bf6f72-9263-5e4d-9861-2e9952a159ad.jpeg)

```java
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class Main {

    public static void main(String[] args) {
        int poolSize = Runtime.getRuntime().availableProcessors();
        System.out.println("poolSize: " + poolSize);

        /**
         * ...
         */
        System.out.println("result: " + result);
    }
}

class Fibonacci extends RecursiveTask<Integer> {
    final int n;
    private String path;

    public Fibonacci(int n, String path) {
        this.n = n;
        this.path = path;
    }

    @Override
    protected Integer compute() {
        this.log("[Start]");

        if (n <= 1) {
            this.log("[ End ]");
            return n;
        }

        /**
         * ...
         */
    }

    private void log(String prefix) {
        StringBuilder buf = new StringBuilder(prefix);

        buf.append("  inPool: ").append(inForkJoinPool());
        buf.append("  queuedTaskCount: ").append(getQueuedTaskCount());
        buf.append("  thread: ").append(Thread.currentThread());
        buf.append("  path: ").append(this.path);

        System.out.println(buf.toString());
    }
}
```

##ForkJoinPool

利用ForkJoinPool來執行task
Main寫法參考如下

```java
        ForkJoinPool pool = new ForkJoinPool(poolSize);
        Integer result = pool.invoke(new Fibonacci(5, "5"));
```

###f2.compute() + f1.join()

參考[クラスRecursiveTask<V>](http://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/RecursiveTask.html)
Fibonacci範例compute實作如下

```java
        Fibonacci f1 = new Fibonacci(n - 1, path + " -> " + (n - 1));
        f1.fork();
        Fibonacci f2 = new Fibonacci(n - 2, path + " -> " + (n - 2));
        this.log("[ End ]");
        return f2.compute() + f1.join();
```

輸出結果如下(**每次結果可能都不同**)

```text
poolSize: 4
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 3 -> 2
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2
[Start]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 1
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 1
result: 5
```

由以上結果來說明`f2 compute()`和`f1 join()`差異

pool.invoke會從pool取得thread`[ForkJoinPool-1-worker-1]`之後
執行new Fibonacci(5, "5")這個task的compute方法
**[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5**
因為5沒有<=1所以拆解
f1 = new Fibonacci(4, ...)並且執行fork將f1放入`[ForkJoinPool-1-worker-1]`的workQuere
queuedTaskCount為**1**

```java
    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;
    }
```

f2 = new Fibonacci(3, ...)
**[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5**

return執行f2的compute方法
所以它會利用現在這個thread`[ForkJoinPool-1-worker-1]`執行Fibonacci(3, ...)的compute方法(path: 5 -> 3)
**[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3**

return另一方面也執行f1的join方法
因為work-stealing queue的特性
pool裡的thread`[ForkJoinPool-1-worker-2]`搶走`[ForkJoinPool-1-worker-1]`workQuere的task(path: 5 -> 4)執行compute方法直到完成可以join為止

```java
    private int doJoin() {
        int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
        return (s = status) < 0 ? s :
            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            (w = (wt = (ForkJoinWorkerThread)t).workQueue).
            tryUnpush(this) && (s = doExec()) < 0 ? s :
            wt.pool.awaitJoin(w, this, 0L) :
            externalAwaitDone();
    }
```

**[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4**

3沒有<=1所以繼續拆解
f1 = new Fibonacci(2, ...)並且執行fork將f1放入[ForkJoinPool-1-worker-**1**]的workQuere
queuedTaskCount為**1**
f2 = new Fibonacci(1, ...)
**[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3**

**[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1**
1<=1所以return 1
**[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1**

其餘請同上類推...

###f2.join() + f1.join()

Fibonacci範例compute實作如下

```java
        Fibonacci f1 = new Fibonacci(n - 1, path + " -> " + (n - 1));
        f1.fork();
        Fibonacci f2 = new Fibonacci(n - 2, path + " -> " + (n - 2));
        f2.fork();
        this.log("[ End ]");
        return f2.join() + f1.join();
```

輸出結果如下(**每次結果可能都不同**)

```text
poolSize: 4
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 3 -> 2
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-0,5,main]  path: 5 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-0,5,main]  path: 5 -> 3 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-0,5,main]  path: 5 -> 4 -> 3
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-0,5,main]  path: 5 -> 4 -> 3
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-0,5,main]  path: 5 -> 4 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-0,5,main]  path: 5 -> 4 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 3 -> 2
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-3,5,main]  path: 5 -> 4 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-2,5,main]  path: 5 -> 4 -> 2
result: 5
```

**[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5**
f1 = new Fibonacci(4, ...)並且執行fork將f1放入`[ForkJoinPool-1-worker-1]`的workQuere
f2 = new Fibonacci(3, ...)並且執行fork將f2放入`[ForkJoinPool-1-worker-1]`的workQuere
所以queuedTaskCount總數為**2**
**[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5**

其餘請同上類推...

###f2.compute() + f1.compute()

Fibonacci範例compute實作如下

```java
        Fibonacci f1 = new Fibonacci(n - 1, path + " -> " + (n - 1));
        Fibonacci f2 = new Fibonacci(n - 2, path + " -> " + (n - 2));
        this.log("[ End ]");
        return f2.compute() + f1.compute();
```

輸出結果如下(**每次結果都相同**)

```text
poolSize: 4
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 3 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 2
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 2
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool-1-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
result: 5
```

單純的recursive堆疊概念
single thread`[ForkJoinPool-1-worker-1,5,main]`有序列執行task的compute方法
不管執行幾次結果順序都會是一樣的
沒有平行處理的能力

##Main Thread

利用main thread來執行task
Main寫法參考如下

```java
        Integer result = new Fibonacci(5, "5").compute();
```

Fibonacci範例同以上第一個例子f2.compute() + f1.join()

輸出結果如下(**每次結果可能都不同**)

```text
poolSize: 4
[Start]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5
[ End ]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4
[Start]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5 -> 3
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 2
[ End ]  inPool: true  queuedTaskCount: 2  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 2
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3
[Start]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3 -> 1
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 4 -> 3 -> 2 -> 0
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4 -> 3 -> 2 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-3,5,main]  path: 5 -> 3 -> 2
[ End ]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5 -> 3
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 3 -> 2 -> 1
[ End ]  inPool: true  queuedTaskCount: 1  thread: Thread[ForkJoinPool.commonPool-worker-3,5,main]  path: 5 -> 3 -> 2
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-2,5,main]  path: 5 -> 3 -> 2 -> 1
[Start]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5 -> 3 -> 1
[ End ]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5 -> 3 -> 1
[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-3,5,main]  path: 5 -> 3 -> 2 -> 0
[ End ]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-3,5,main]  path: 5 -> 3 -> 2 -> 0
result: 5
```

每次結果雖然可能都不同
但是main thread一定會執行task(path: 5)
而且main thread不在pool中所以inPool為false
**[Start]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5**
f1 = new Fibonacci(4, ...)並且使用main thread來執行fork方法
因為不是使用ForkJoinWorkerThread緣故
所以f1放入`ForkJoinPool.common.externalPush(this);`
f2 = new Fibonacci(3, ...)
**[ End ]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5**

剛剛提到的f1在join時會使用ForkJoinWorkerThread來執行task(path: 5 -> 4)的compute方法
**[Start]  inPool: true  queuedTaskCount: 0  thread: Thread[ForkJoinPool.commonPool-worker-1,5,main]  path: 5 -> 4**
由`[ForkJoinPool.commonPool-worker-1,5,main]`來執行compute方法直到完成可以join為止

而f2則繼續由main thread來執行task(path: 5 -> 3)的compute方法
**[Start]  inPool: false  queuedTaskCount: 0  thread: Thread[main,5,main]  path: 5 -> 3**

其餘請同上類推...

##ref.
[ForkJoinPool Example (Java Concurrency - Part 2)](http://www.hsufengko.com/home/forkjoinpool-example)
[ForkJoinPoolとForkJoinTaskの使い方とブロッキングの実装方法](http://d.hatena.ne.jp/seraphy/20140504)
[聊聊并发（八）——Fork/Join框架介绍](http://www.infoq.com/cn/articles/fork-join-introduction)