Multithreading 递归动作是如何工作的?

Multithreading 递归动作是如何工作的?,multithreading,threadpool,fork-join,forkjoinpool,Multithreading,Threadpool,Fork Join,Forkjoinpool,我从网上下载了一些现有的代码。我运行它时几乎没有修改。在一个场景中,我没有得到我想要的东西。这是密码- import java.util.ArrayList; import java.util.List; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveAction; public class MyRecursiveAction extends RecursiveAction{

我从网上下载了一些现有的代码。我运行它时几乎没有修改。在一个场景中,我没有得到我想要的东西。这是密码-

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class MyRecursiveAction extends RecursiveAction{

    private long workload = 0;

    public MyRecursiveAction(long workload) {
        this.workload = workload;
    }

    @Override
    protected void compute() {

        if(this.workload > 16) {
            System.out.println("Splitting workload :: " + this.workload);
            List<MyRecursiveAction> subtasks = new ArrayList<MyRecursiveAction>();
            subtasks.addAll(createSubtasks());
            for(RecursiveAction subtask : subtasks) {
                subtask.fork();
            }
        }else {
            System.out.println("Doing work myself1 " + this.workload);
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Done it ya " + this.workload);
        }

    }

    private List<MyRecursiveAction> createSubtasks() {
        List<MyRecursiveAction> subTasks = new ArrayList<>();
        MyRecursiveAction subtask1 = new MyRecursiveAction(this.workload / 2);
        MyRecursiveAction subtask2 = new MyRecursiveAction(this.workload / 2);
        subTasks.add(subtask1);
        subTasks.add(subtask2);
        return subTasks;
    }

    public static void main(String[] args) {
        MyRecursiveAction myRecursiveAction = new MyRecursiveAction(24);
        ForkJoinPool forkJoinPool = new ForkJoinPool(4);
        forkJoinPool.invoke(myRecursiveAction);
    }

}
我加了一秒钟的睡眠时间,然后打印了另一份声明。但是,如果我运行代码,我看不到该语句被打印出来。我不明白为什么。为什么不能打印出来?事实上,执行的结果是-

Splitting workload :: 24
Doing work myself1 12
Doing work myself1 12

我还期待着下面这句话——“Done it ya”。

使工作负载保持静态和不稳定:

private static volatile long workload = 0;
松开this.workload,只为工作负载。 将if语句更改为:

if(workload > 0) {

然后您将看到“Done it ya”。

我找到了最后一行未打印的原因。这是因为fork以异步方式工作。因此,这是一条完全不同的线,它会休眠一段时间。在异步编程中,主线程不需要等待响应返回,除非我们通过代码添加一些构造。在这种情况下,当线程在1秒后醒来时,主线程已经结束

为了强制主线程等待其他线程的执行,我们需要使用JOIN

ForkJoinTask.join():此方法将阻塞,直到计算结果完成

因此,如果我添加以下块

    for(RecursiveAction subtask : subtasks) {
        subtask.join();
    }

主线程等待,我们将在控制台上打印所有预期的行。

好的,您是要评论下面的帖子还是接受它?很抱歉延迟确认您的答案。我正在寻找为什么它不能从我写的代码工作。一旦我理解了原因,我就可以从你的答案中得到“如何修复它”。它不起作用,因为当你得到一个新的MyRecursiveAction(this.workload/2);您还将在该对象中获得一个新的工作负载变量,并且它是您随后测试的新变量。这就是为什么工作负载是静态的和不稳定的。我明白了。但对于分叉任务(MyRecursiveAction(this.workload/2)),将调用compute方法。在那里,新的工作量值小于16。所以应该打印sysout,rt?@user3276247在IDE中调试程序。您将看到,这个.workload永远不会改变。可以在main()的末尾添加睡眠或其他内容,以使所有对象可见。“this”指的是原始对象。我说使用static的原因是为了更容易理解。使用“this”时必须非常小心,它很容易丢失。异步的目的是不使用join()。你回答了自己的问题,然后接受了。下次只需编辑您的原始问题。好的,我现在不接受答案。我想既然我问了这个问题,而且这个答案满足了我的要求,我也接受了。我不知道这违反了任何社区标准。我还想知道为什么这行没有被打印出来。我的回答解释了这一点。我来这里不是为了讨论异步的目的。
    for(RecursiveAction subtask : subtasks) {
        subtask.join();
    }