首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RecursiveTask线程不会被join()阻塞

RecursiveTask线程不会被join()阻塞
EN

Stack Overflow用户
提问于 2019-11-29 06:45:21
回答 1查看 143关注 0票数 2

我有以下代码:

代码语言:javascript
复制
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

但是,该代码的输出是:

线程启动,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

EN

回答 1

Stack Overflow用户

发布于 2019-11-30 19:07:38

连接()Fork池中与经典的线程连接不同。

join ()在Java线程中用作屏障同步器,以等待另一个线程完成,然后与其连接(在完成另一个线程之前不能继续)。常规线程中的联接会阻塞调用线程。

join()在Fork池中并不是简单地阻塞调用线程,而是使用工作线程来帮助运行子任务。

当workerThread遇到join()时,它会处理任何其他任务,直到它注意到目标子任务已经完成为止。

在这个子任务结果完成之前,workerThread不会返回给调用方。

一个 join() 在Fork-Join 任务中不是阻塞的,它包含当前的任务,因此只有在join()创建的子任务完成之后,计算才会继续。

工作线程指出,任务被阻塞,直到子任务完成,所以它开始工作在子任务上。

ForkJoinTask比Java线程轻。一个真正的Java线程有它自己的堆栈、寄存器,以及许多其他的资源,这些资源允许由线程调度程序独立地管理它,这些资源是操作系统内部拥有的。

在ForkJoinTask中,大量的ForkJoinTask可以在少得多的WorkerThreads中运行。每个WorkerThread都是一个Java线程对象,它具有您期望从一个普通线程获得的所有设备。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59099949

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档