【问题标题】:ForkJoinTask understandingForkJoinTask 理解
【发布时间】:2016-02-27 23:16:58
【问题描述】:

subtask.fork() 返回ForkJoinTask<Int> 对象后会发生什么?之后,compute() 方法被调用了很多次,但是从哪里以及如何调用?

我是 Java 新手,我正在尝试学习 fork/join 框架的概念。我在网上看到了下面的代码。我在阅读 Java API 后知道subtask.fork() 返回一个ForkJoinTask<V> 的对象,在这种情况下是ForkJoinTask<Int>。我无法理解的是之后会发生什么?输出表明 compute() 方法在此之后已被多次调用,但从何处以及如何调用?

public class MyRecursiveAction extends RecursiveAction {

    public static void main(String[] args) {
        MyRecursiveAction mra1 = new MyRecursiveAction(100);
        ForkJoinPool fjp1 = new ForkJoinPool();
        fjp1.invoke(mra1);
    }

    private long workLoad = 0;

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

    @Override
    protected void compute() {

        //if work is above threshold, break tasks up into smaller tasks
        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 workLoad myself: " + this.workLoad);
        }
    }

    private List<MyRecursiveAction> createSubtasks() {
        List<MyRecursiveAction> subtasks =
            new ArrayList<MyRecursiveAction>();

        MyRecursiveAction subtask1 = new MyRecursiveAction(this.workLoad / 2);
        MyRecursiveAction subtask2 = new MyRecursiveAction(this.workLoad / 2);

        subtasks.add(subtask1);
        subtasks.add(subtask2);

        return subtasks;
    }

}

输出:

Splitting workLoad : 100
Splitting workLoad : 50
Splitting workLoad : 50
Splitting workLoad : 25
Doing workLoad myself: 12
Doing workLoad myself: 12
Splitting workLoad : 25
Doing workLoad myself: 12
Doing workLoad myself: 12
Splitting workLoad : 25
Doing workLoad myself: 12
Splitting workLoad : 25
Doing workLoad myself: 12
Doing workLoad myself: 12
Doing workLoad myself: 12

【问题讨论】:

    标签: java multithreading threadpool fork-join


    【解决方案1】:

    您需要调用 invokeAll 以便将您的工作分成两部分而不是手动执行,然后将创建 2 个新线程来“计算”您的结果,然后如果它不够小,则 2 个新线程等等..,

    您无法预测线程将以什么顺序执行,因此每次运行此代码时消息顺序都会有所不同。

    public class MyRecursiveAction extends RecursiveAction {
    
        public static void main(String[] args) {
            MyRecursiveAction mra1 = new MyRecursiveAction(100);
            ForkJoinPool fjp1 = new ForkJoinPool();
            fjp1.invoke(mra1);
        }
    
        private long workLoad = 0;
    
        public MyRecursiveAction(long workLoad) {
            this.workLoad = workLoad;
        }
    
        @Override
        protected void compute() {
    
            //if work is above threshold, break tasks up into smaller tasks
            if(this.workLoad > 16) {
                System.out.println("Splitting workLoad : " + this.workLoad);
    
                invokeAll(new MyRecursiveAction(this.workLoad / 2), new MyRecursiveAction(this.workLoad / 2));
    
            } else {
                System.out.println("Doing workLoad myself: " + this.workLoad);
            }
        }
    
    }
    

    Java doc of ForkJoinTask

    【讨论】:

    • 非常感谢您的帮助。真的很感激。但是,我还有一个问题希望您能帮助我回答。在invokeAll(new MyRecursiveAction(this.workload / 2), new MyRecursiveAction(this.workload / 2)) 之后,每个新创建的MyRecursiveAction 对象都会马上再次调用MyRecursiveAction.compute() 方法吗?这是正确的吗?
    • 不是马上,这将取决于他们的线程何时处于活动状态,但计算将被称为是。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多