RecursiveAction如何工作?

时间:2017-06-02 10:42:25

标签: 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{

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

}

检查以下摘录 -

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

我加了1秒的睡眠,然后又打印了另一个声明。但是,如果我运行代码,我就不会看到该语句被打印出来。我不明白为什么。为什么不打印?实际上执行的结果是 -

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

我也期待以下一行 - &#34;完成它&#34; ..

2 个答案:

答案 0 :(得分:1)

使工作负载静态和易变:

private static volatile long workload = 0;

只为工作负载放松this.workload。 如果声明改为:

if(workload > 0) {

然后你会得到“完成它”。

答案 1 :(得分:0)

我找到了为什么最后一行没有被打印的原因。这是因为fork以异步方式工作。所以它完全是一个不同的线程,睡了一段时间。在异步编程中,除非我们通过代码添加一些结构,否则主线程不需要等待响应返回。在这种情况下,时间线程在1秒后唤醒,主线程已经结束。

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

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

所以如果我添加以下块

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

主线程等待,我们得到控制台上打印的所有预期线条。