我有以下代码:
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结果= 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结果= 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结果= 1
线程 完成,threadId = 11 n = 3 activeCount = 3结果= 2
线程 完成,threadId = 11 n = 4 activeCount = 3 result = 3
线程 完成,threadId = 11 n = 5 activeCount = 3 result = 5
从输出打印中可以看到,我们一次有12个线程处于活动状态。
尽管 parallelism为1 ,如何打开新线程?
答案 0 :(得分:2)
join() 与经典的Java线程联接不同。
< Java线程中的em> join() 用作屏障同步器,以等待另一个线程结束,然后再加入它(直到另一个完成)。常规线程中的联接会阻止调用线程。
Fork-Join池中的 join() 并不只是阻塞调用线程,而是使用辅助线程来帮助您运行子任务。
当workerThread遇到 join() 时,它将处理其他所有任务,直到发现目标子任务已完成。
workerThread不会返回到直到此子任务结果完成为止。
Fork-Join池任务中的 join() 未被阻止,它保存了当前任务,因此仅在它是由join()完成创建的子任务。
工作线程发现,直到子任务完成,任务才被阻塞,因此它开始在子任务上工作。
ForkJoinTask比Java线程轻。真正的Java线程具有其自己的堆栈,寄存器以及许多其他资源,这些资源使操作系统可以在内部由线程调度程序独立地对其进行调度。
在Fork-Join-Pool中,大量的ForkJoinTask可以在数量少得多的WorkerThreads中运行。每个WorkerThread是一个Java线程对象,具有您希望从普通线程获得的所有装备。