在Java 7中使用Fork Join的斐波那契

时间:2018-07-19 04:32:16

标签: java-7 forkjoinpool

这是一个使用Java 7 ForkJoin的Fibonacci程序。 但是似乎有一个死锁。

package ForkJoin;

import java.time.LocalTime;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

import static java.time.temporal.ChronoUnit.MILLIS;

class Fibonacci extends RecursiveTask<Integer>{

    int num;
    Fibonacci(int n){
        num = n;
    }

    @Override
    protected Integer compute() {
        if(num <= 1)
            return num;

        Fibonacci fib1 = new Fibonacci(num-1);
        fib1.fork();
        Fibonacci fib2 = new Fibonacci(num-2);
        fib2.fork();

        return fib1.join()+ fib2.join();
    }
}

public class ForkJoinFibonaaciEx {

    public static void main(String[] arg){
        LocalTime before = LocalTime.now();
        int processors = Runtime.getRuntime().availableProcessors();
        System.out.println("Available core: "+processors);
        ForkJoinPool pool = new ForkJoinPool(processors);
        System.out.println("Inside ForkJoin for number 50:  "+pool.invoke(new Fibonacci(50)));
        LocalTime after = LocalTime.now();
        System.out.println("Total time taken: "+MILLIS.between(before, after));
    }
}

JVisualVM ----显示存在死锁。 不知道真正的问题是什么。

此外,我注意到代码中,开发人员完成了一部分的派生调用,并为问题的另一半进行了计算。

例如在此示例中,它们使用的是fib1.fork()和fib2,它们不会分叉。

您可以看到完整的示例 https://github.com/headius/forkjoin.rb/blob/master/examples/recursive/Fibonacci.java

非常感谢您的帮助。 谢谢你,祝你生活愉快 带着敬意 十日假人

2 个答案:

答案 0 :(得分:0)

通过在计算方法中添加 fib2.fork(); ,您将创建之前已经计算过的冗余子任务(即在下一个递归调用 fib1.fork()< / strong>)。最终添加多余的子任务,这将花费额外的时间。相反,您可以调用 fib2.compute(),依次调用递归中的fork。

尽管这不是造成浪费时间的真正原因。真正的问题是由 fork.join()操作引起的。当此操作等待所有子任务(可能由其他线程执行)完成时。 因此,尽管在每个内核上执行多个线程以提供并行性,但是与联接操作相比,叶级别的实际计算可以忽略不计。

底线是:

如果满足以下情况,则应使用fork-join:

  1. 问题可以使用分而治之解决,创建子问题并递归解决。

  2. 问题无法预先划分并且是动态的。

同样,为了使fork-join有效地工作,我们应该将问题仅划分到并行计算的好处大于危害的特定水平。

答案 1 :(得分:0)

试试这个:

class ComputeFibonacciTask extends RecursiveTask<Long> {

    private int n;

    public ComputeFibonacciTask(int n) {
        this.n = n;
    }

    protected Long compute() {
        if (n <= 1) {
            return Long.valueOf(n);
        }

        else {
            RecursiveTask<Long> otherTask = new ComputeFibonacciTask(n - 1);
            otherTask.fork();
            return new ComputeFibonacciTask(n - 2).compute() + otherTask.join();
        }
    }
}