Fibonacci using Fork Join in Java 7

大兔子大兔子 提交于 2021-01-28 20:21:33

问题


This is a program for Fibonacci using Java 7 ForkJoin . But seems like there is a dead lock.

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 ---- shows there is dead lock. Not sure what the real issue is.

Also, I have noticed codes where developers have done fork call for one portion and compute for other half of the problem.

e.g. here in this example they use fib1.fork() and fib2 they don't fork.

You can see the full example https://github.com/headius/forkjoin.rb/blob/master/examples/recursive/Fibonacci.java

Your help is very much appreciated. Thank you and have a great With regards Deenadayal Manikanta


回答1:


By adding fib2.fork(); in the compute method, you are creating redundant subtask that has already been calculated before (i.e In next recursive call of fib1.fork()) . Eventually adding redundant sub-task which will take extra time. Instead you can call fib2.compute() which in turn will call fork in the recursion.

Though this is not the actual culprit for time consuming. Real problem is caused by fork.join() operation. As this operation wait for all child sub task (that might be executed by other thread) to finish. Therefore although there are multiple threads executing at each core providing parallelism, the actual computation at leaf level is negligible compared to join operation.

Bottom line is:

We should use fork-join if below cases are true:

  1. Problem can be solved using Divide and Conquer, creating sub-problem and recursively solve it.

  2. Problem can't be divided upfront and is dynamic.

Also for fork-join to work effectively, we should divide the problem to only a certain level where parallel computation does more good than harm.




回答2:


Try this:

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


来源:https://stackoverflow.com/questions/51414388/fibonacci-using-fork-join-in-java-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!