这是一个使用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
非常感谢您的帮助。 谢谢你,祝你生活愉快 带着敬意 十日假人
答案 0 :(得分:0)
通过在计算方法中添加 fib2.fork(); ,您将创建之前已经计算过的冗余子任务(即在下一个递归调用 fib1.fork()< / strong>)。最终添加多余的子任务,这将花费额外的时间。相反,您可以调用 fib2.compute(),依次调用递归中的fork。
尽管这不是造成浪费时间的真正原因。真正的问题是由 fork.join()操作引起的。当此操作等待所有子任务(可能由其他线程执行)完成时。 因此,尽管在每个内核上执行多个线程以提供并行性,但是与联接操作相比,叶级别的实际计算可以忽略不计。
底线是:
如果满足以下情况,则应使用fork-join:
问题可以使用分而治之解决,创建子问题并递归解决。
问题无法预先划分并且是动态的。
同样,为了使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();
}
}
}