Java RecursiveTask 分叉与计算

Java RecursiveTask fork vs compute

我有使用 RecursiveTask 的 febunacci 算法的代码,我在

中找到了它

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/RecursiveTask.html

代码 1

public class Fibonacci extends RecursiveTask<Integer> {
   final int n;
   public Fibonacci (int n) { this.n = n; }
   public Integer compute() {
     if (n <= 1)
        return n;
     Fibonacci  f1 = new Fibonacci(n - 1);
     f1.fork();
     Fibonacci  f2 = new Fibonacci(n - 2);
 return f2.compute() + f1.join();

   }
   public static void main(String args[]){
       ForkJoinPool fjpool = new ForkJoinPool();

        RecursiveTask task = new Fibonacci(30);
        long startTime1=System.currentTimeMillis();;
        Integer O=(Integer) fjpool.invoke(task);
        long endTime1 =  System.currentTimeMillis();
        long duration1 = (endTime1 - startTime1);
        System.out.println(duration1);

   }}

此代码在 83 毫秒内执行,我对其进行了修改

代码 2

public class Fibonacci extends RecursiveTask<Integer> {
   final int n;
   public Fibonacci (int n) { this.n = n; }
   public Integer compute() {
     if (n <= 1)
        return n;
     Fibonacci  f1 = new Fibonacci(n - 1);

     Fibonacci  f2 = new Fibonacci(n - 2);
 return f2.compute() + f1.compute();

   }
   public static void main(String args[]){
       ForkJoinPool fjpool = new ForkJoinPool();

        RecursiveTask task = new Fibonacci(30);
        long startTime1=System.currentTimeMillis();;
        Integer O=(Integer) fjpool.invoke(task);
        long endTime1 =  System.currentTimeMillis();
        long duration1 = (endTime1 - startTime1);
        System.out.println(duration1);

   }}

现在这段代码在 20 毫秒内执行,有人可以解释为什么第二个更快我阅读了文档它说 fork 异步执行然后为什么它 运行 比使用计算慢。

第一个解决方案可能执行不佳,因为最小的子任务太小,不值得拆分。

RecursiveTask task = new Fibonacci(30);

相反,与几乎所有 fork/join 应用程序的情况一样,您会选择一些最小粒度(例如这里的 30),您总是按顺序解决而不是细分。

请记住,Fork/Join 框架在并行处理更大的数据集时非常庞大。

来源

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/RecursiveTask.html

因为 +compute() 不使用池中的新线程,而且它不是 运行 在池管理的线程中。 当池调用许多 RecursiveTask 时,您将看到 +join() 的并行性优势。那么如果compute方法中有等待或者阻塞,它的线程就会被其他任务使用。所以线程会更少。