簡體   English   中英

RecursiveTask 線程未被 join() 阻塞

[英]RecursiveTask thread is not blocked by join()

我有以下代碼:

public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newWorkStealingPool(1);
        ForkJoinPool workStealingPool = (ForkJoinPool)executorService;
        RecursiveRunnable recursiveRunnable = new RecursiveRunnable(5);
        workStealingPool.invoke(recursiveRunnable);
    }
}
public class RecursiveRunnable extends RecursiveTask<Integer> implements Runnable {
    private final int n;

    public RecursiveRunnable(int n) {
        this.n = n;
    }

    @Override
    @SneakyThrows
    protected Integer compute() {
        Thread thread = Thread.currentThread();
        System.out.println("Thread started, threadId=" + thread.getId() + " n=" + n +  " activeCount=" + Thread.activeCount());
        if (n <= 1) {
            return n;
        }
        RecursiveRunnable f1 = new RecursiveRunnable(n - 1);
        f1.fork();
        RecursiveRunnable f2 = new RecursiveRunnable(n - 2);
        f2.fork();
        int result = 0;
        result = f2.get() + f1.get();
        System.out.println("Thread finished,  threadId=" + thread.getId() + " n=" + n +  " activeCount=" + Thread.activeCount() + " result=" + result);
        return result;
    }

    @Override
    public void run() {
        compute();
    }
}

我希望代碼不會在fork()語句中打開新線程,
因為並行度是 1
但是這段代碼的輸出是:

線程啟動,threadId=11 n=5 activeCount=3
線程啟動,threadId=11 n=3 activeCount=3
線程啟動,threadId=11 n=1 activeCount=3
線程啟動,threadId=11 n=2 activeCount=3
線程啟動,threadId=11 n=0 activeCount=3
線程啟動,threadId=11 n=1 activeCount=3
線程完成,threadId=11 n=2 activeCount=3 result=1
線程完成,threadId=11 n=3 activeCount=3 result=2
線程啟動,threadId=11 n=4 activeCount=3
線程啟動,threadId=11 n=2 activeCount=3
線程啟動,threadId=11 n=0 activeCount=3
線程啟動,threadId=11 n=1 activeCount=3
線程完成,threadId=11 n=2 activeCount=3 result=1
線程啟動,threadId=11 n=3 activeCount=3
線程啟動,threadId=11 n=1 activeCount=3
線程啟動,threadId=11 n=2 activeCount=3
線程啟動,threadId=11 n=0 activeCount=3
線程啟動,threadId=11 n=1 activeCount=3
線程完成,threadId=11 n=2 activeCount=3 result=1
線程完成,threadId=11 n=3 activeCount=3 result=2
線程完成,threadId=11 n=4 activeCount=3 result=3
線程完成,threadId=11 n=5 activeCount=3 result=5

從輸出打印來看,我們似乎同時有 12 個線程處於活動狀態。
盡管並行度為 1 ,但如何打開新線程?

Fork-Join 池中join()不同於經典的 Java 線程連接。
Java 線程中的join()用作屏障同步器以等待另一個線程完成,然后您加入它(在另一個線程完成之前您不能繼續)。 常規線程中的連接會阻塞調用線程。
Fork-Join 池中join()不會簡單地阻塞調用線程,相反,工作線程用於幫助運行子任務。
當 workerThread 遇到join()時,它會處理任何其他任務,直到它注意到目標子任務已完成。
在這個子任務結果完成之前,workerThread 不會返回給調用者。
Fork-Join 池任務中的join()不是阻塞的,它持有當前任務,因此只有在 join() 創建的子任務完成后才能繼續計算。
工作線程發現,任務被阻塞,直到子任務完成,所以它開始處理子任務。
ForkJoinTask 比 Java 線程更輕。 一個真正的 Java 線程有它自己的堆棧、寄存器和許多其他資源,這些資源允許它由操作系統內部的線程調度程序獨立管理。
大量的 ForkJoinTask 可以運行在 Fork-Join-Pool 中數量少得多的 WorkerThreads 中。 每個 WorkerThread 都是一個 Java 線程對象,具有您期望從普通線程獲得的所有裝備。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM