Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ExecutorService解决递归斐波那契级数_Java_Multithreading_Recursion_Fibonacci_Executorservice - Fatal编程技术网

Java ExecutorService解决递归斐波那契级数

Java ExecutorService解决递归斐波那契级数,java,multithreading,recursion,fibonacci,executorservice,Java,Multithreading,Recursion,Fibonacci,Executorservice,我需要使用线程递归地根据斐波那契数列中的某个索引找出数字,我尝试了以下代码,但程序永远不会结束。如果我遗漏了什么,请告诉我 代码: import java.math.BigInteger; import java.util.concurrent.*; public class MultiThreadedFib { private ExecutorService executorService; public MultiThreadedFib(final int

我需要使用线程递归地根据斐波那契数列中的某个索引找出数字,我尝试了以下代码,但程序永远不会结束。如果我遗漏了什么,请告诉我

代码

  import java.math.BigInteger;
  import java.util.concurrent.*;

  public class MultiThreadedFib {

    private ExecutorService executorService;

    public MultiThreadedFib(final int numberOfThreads) {
      executorService = Executors.newFixedThreadPool(numberOfThreads);
    }

    public BigInteger getFibNumberAtIndex(final int index) 
      throws InterruptedException, ExecutionException {

      Future<BigInteger> indexMinusOne = executorService.submit(
        new Callable<BigInteger>() {
          public BigInteger call() 
          throws InterruptedException, ExecutionException {
            return getNumber(index - 1);
          }
      });

      Future<BigInteger> indexMinusTwo = executorService.submit(
        new Callable<BigInteger>() {
          public BigInteger call() 
          throws InterruptedException, ExecutionException {
            return getNumber(index - 2);
          }
      });

      return indexMinusOne.get().add(indexMinusTwo.get());
    }

    public BigInteger getNumber(final int index) 
    throws InterruptedException, ExecutionException {
      if (index == 0 || index == 1)
        return BigInteger.valueOf(index);

      return getFibNumberAtIndex(index - 1).add(getFibNumberAtIndex(index - 2));
    }
  }
import java.math.biginger;
导入java.util.concurrent.*;
公共类多线程FIB{
私人遗嘱执行人服务;
公共多线程FIB(最终整数线程数){
executorService=Executors.newFixedThreadPool(线程数);
}
public BigInteger GetFibNumberIndex(最终整数索引)
抛出InterruptedException、ExecutionException{
Future indexMinusOne=executorService.submit(
新的可调用(){
公共BigInteger调用()
抛出InterruptedException、ExecutionException{
返回getNumber(索引-1);
}
});
Future indexMinusTwo=executorService.submit(
新的可调用(){
公共BigInteger调用()
抛出InterruptedException、ExecutionException{
返回getNumber(索引-2);
}
});
返回indexMinusOne.get().add(indexMinusTwo.get());
}
public BigInteger getNumber(最终整数索引)
抛出InterruptedException、ExecutionException{
如果(索引=0 | |索引=1)
返回BigInteger.valueOf(索引);
返回getFibNumberIndex(索引-1)。添加(getFibNumberIndex(索引-2));
}
}
修复了它(感谢fiver)

我不是从call方法调用getNumber(int),而是调用一个动态编程算法,该算法计算该索引处的数字

其代码为:

public class DynamicFib implements IFib {

private Map<Integer, BigInteger> memoize = new HashMap<Integer, BigInteger>();

public DynamicFib() {
  memoize.put(0, BigInteger.ZERO);
  memoize.put(1, BigInteger.ONE);
}

public BigInteger getFibNumberAtIndex(final int index) {

  if (!memoize.containsKey(index))
    memoize.put(index, getFibNumberAtIndex(index - 1).add(getFibNumberAtIndex(index - 2)));

  return memoize.get(index);
  }
}
公共类DynamicFib实现IFib{
私有映射memoize=newhashmap();
公共动态ib(){
memoize.put(0,BigInteger.0);
memoize.put(1,BigInteger.1);
}
public BigInteger GetFibNumberIndex(最终整数索引){
如果(!memoize.containsKey(索引))
memoize.put(索引,getFibNumberIndex(索引-1).add(getFibNumberIndex(索引-2));
返回memoize.get(索引);
}
}

此递归将很快溢出堆栈。这是因为你一次又一次地计算较低的斐波那契数,次数是指数级的

避免这种情况的一种有效方法是使用记忆递归(一种动态编程方法)

基本上使用一个静态数组来保存已经计算过的斐波那契数,如果需要的话,可以从数组中取出。如果不是,则计算它并将其存储在数组中。这样,每个数字只计算一次


(当然,您可以使用其他数据结构而不是数组,即哈希表)

您所做的是通过线程/任务将简单递归替换为递归

在处理fib(0)和fib(1)案例之前,每个任务都会再提交两个任务,然后等待它们完成。在等待时,它仍在使用线程。由于线程池是有界的,您很快就会到达调用
submit
block。。。整个计算都被锁定了


除此之外,
indexMinusTwo
中还有一个bug,这将导致计算给出错误的答案



但是递归多线程过程仍然比记忆的递归非多线程过程花费更长的时间。。有什么提高性能的建议吗


即使假设您“修复”了上述问题(例如,通过使用无界线程池),您也不可能实现多线程版本的fibonacci,该版本的性能优于使用记忆的单线程版本。计算根本不适合并行化。

当您有独立任务要执行时,线程工作得最好。根据定义,斐波那契级数没有任何平行度。每个f(n)取决于前两个值。因此,使用多个线程比使用一个线程计算f(n)要快是不可能的(除非您有一个低效的算法)

对于大量的数据,您唯一可以使
+
操作并行化的方法可能是a)复杂b)难以比单线程解决方案更快地实现


计算斐波那契数的最快/最简单的方法是在一个线程中使用循环。您不需要使用递归或记忆值。

但递归多线程过程仍然比记忆的递归非多线程过程耗时更长。。有什么提高性能的技巧吗?好吧,那就是点简单递归永远不会完成(即使是多线程),因为迭代次数呈指数增长如果你想更快,你可以执行多线程的记忆递归(只需要同步arrray)。谢谢你的澄清。但是,请让我知道代码中的错误到底在哪里