java - RecursiveTask 线程不会被 join() 阻塞

标签 java multithreading executor fork-join forkjoinpool

我有以下代码:

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();
    }
}

我希望代码不会在 中打开新线程叉()声明,自 并行度为 1 .
但是这段代码的输出是:

Thread started, threadId=11 n=5 activeCount=3
Thread started, threadId=11 n=3 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread started, threadId=11 n=2 activeCount=3
Thread started, threadId=11 n=0 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread finished, threadId=11 n=2 activeCount=3 result=1
Thread finished, threadId=11 n=3 activeCount=3 result=2
Thread started, threadId=11 n=4 activeCount=3
Thread started, threadId=11 n=2 activeCount=3
Thread started, threadId=11 n=0 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread finished, threadId=11 n=2 activeCount=3 result=1
Thread started, threadId=11 n=3 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread started, threadId=11 n=2 activeCount=3
Thread started, threadId=11 n=0 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread finished, threadId=11 n=2 activeCount=3 result=1
Thread finished, threadId=11 n=3 activeCount=3 result=2
Thread finished, threadId=11 n=4 activeCount=3 result=3
Thread finished, threadId=11 n=5 activeCount=3 result=5



从输出打印来看,我们一次有 12 个线程处于 Activity 状态。
尽管 如何打开新线程并行度为 1 ?

最佳答案

加入() fork 加入池不同于经典的 Java 线程连接。 加入() Java线程用作屏障同步器以等待另一个线程完成然后您加入它(在另一个线程完成之前您无法继续)。常规线程中的连接会阻塞调用线程。
加入() fork 加入池不是简单地阻塞调用线程,而是使用工作线程来帮助运行子任务。
当 workerThread 遇到 加入() 它处理任何其他任务,直到它注意到目标子任务完成。在此子任务结果完成之前,workerThread 不会返回给调用者。
A 加入() fork 加入池任务不是块,它保存当前任务,因此只有在 join() 创建的子任务完成后才能继续计算。工作线程发现,任务被阻塞,直到子任务完成,所以它开始处理子任务。
ForkJoinTask 比 Java 线程轻。一个真正的 Java 线程有它自己的堆栈、寄存器和许多其他资源,这些资源允许它由操作系统内部具有的线程调度程序独立管理。
大量的 ForkJoinTask 可以在 Fork-Join-Pool 中的少量 WorkerThread 中运行。每个 WorkerThread 都是一个 Java 线程对象,具有您期望从普通线程获得的所有装备。

关于java - RecursiveTask 线程不会被 join() 阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59099949/

相关文章:

java - 从 jar 运行时,处理 2.0 电影无法打开电影文件

javascript - 访问异步函数之外的变量时的JS安全性

c++ - 多线程导致Qt运行时报错

java - 向单线程目录中所有文件迭代器实用函数添加多线程可能性

java - OpenGL es glDrawTexfOES() 2D纹理不渲染

java - 如何定义我的 ItemReader : Spring batch, JPA

Java 执行器 : how can I set task priority?

java - 在 Java 中运行基于 cpu 的任务的简单程序的最佳线程池大小是多少

java - 查找java程序中方法数的程序

java - CLR 是否执行 "lock elision"优化?如果不是,为什么不呢?