[英]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.