在Java中使用线程和递归来计算Fibonacci数

时间:2009-04-01 15:25:52

标签: java multithreading recursion

我在Java世界中比较新,我遇到了一个我不明白的问题。

我有一个Class(获取斐波纳契行):

class Fib {
    public static int f(int x){
        if ( x < 2 )
            return 1;       
        else 
            return f(x-1)+ f(x-2);      
    }
}

现在的任务是在一个单独的线程中启动f(x-1)和f(x-2)。 一次实现Thread类,另一次实现Runnable。 你可能知道,这是我教授的练习。

我知道如何在Java中启动一个Thread,我知道整个Thread事物在理论上是如何工作的,但我找不到在这个递归函数中启动单独Threads的解决方案。

在run函数中需要做什么?

可能

public void run(){
//int foo=start f(this.x-1)
    //int bar=start f(this.x-2)  
    //return foo+bar?
}

如何在我的runnable函数中粘贴x? x是否在创建时传递给对象?

Class Fib ...{
  int x;
  public ... run ... 
  public ... f(x)....

}

主要方法

(new Fib(x)).start();

或者我走错了路?

4 个答案:

答案 0 :(得分:10)

为了使其工作,您需要1)一种方法将数字传递给新线程,2)启动线程,3)等待线程完成,以及4)获得结果的方法从线程。

您可以通过构造函数传递数字。您可以拥有一个名为“answer”的公共数据成员来包含计算结果。可以使用start()方法启动线程,join()方法等待线程完成。

以下示例演示了这一点。这应该是一个很好的起点;从这里你可以抽象出一些混乱,以获得更好的API。

public class Fib extends Thread
{
    private int x;
    public int answer;

    public Fib(int x) {
        this.x = x;
    }

    public void run() {
        if( x <= 2 )
            answer = 1;
        else {
            try {
                Fib f1 = new Fib(x-1);
                Fib f2 = new Fib(x-2);
                f1.start();
                f2.start();
                f1.join();
                f2.join();
                answer = f1.answer + f2.answer;
            }
            catch(InterruptedException ex) { }
        }
    }

    public static void main(String[] args)
        throws Exception
    {
        try {
            Fib f = new Fib( Integer.parseInt(args[0]) );
            f.start();
            f.join();
            System.out.println(f.answer);
        }
        catch(Exception e) {
            System.out.println("usage: java Fib NUMBER");
        }
    }
}

答案 1 :(得分:7)

使用线程通常是为了提高性能。但是,每个线程都会增加开销,如果执行的任务很小,那么可能会比实际完成的工作多得多。此外,大多数PC只能处理大约1000个线程,如果你的线程超过10K,它们就会挂起。

在你的情况下,fib(20)将生成6765个线程,fib(30)创建832K,fib(40)创建102M线程,fib(50)创建超过12万亿。我希望你能看到这是不可扩展的。

但是,使用不同的方法,您可以在一分钟内计算出fib(1000000)。

import java.math.BigInteger;

/*
250000th fib # is: 36356117010939561826426 .... 10243516470957309231046875
Time to compute: 3.466557 seconds.
1000000th fib # is: 1953282128707757731632 .... 93411568996526838242546875
Time to compute: 58.1 seconds.
*/
public class Main {
    public static void main(String... args) {
        int place = args.length > 0 ? Integer.parseInt(args[0]) : 250 * 1000;
        long start = System.nanoTime();
        BigInteger fibNumber = fib(place);
        long time = System.nanoTime() - start;

        System.out.println(place + "th fib # is: " + fibNumber);
        System.out.printf("Time to compute: %5.1f seconds.%n", time / 1.0e9);
    }

    private static BigInteger fib(int place) {
        BigInteger a = new BigInteger("0");
        BigInteger b = new BigInteger("1");
        while (place-- > 1) {
            BigInteger t = b;
            b = a.add(b);
            a = t;
        }
        return b;
    }
}

答案 2 :(得分:2)

你有关于在fib函数中启动线程以及通过构造函数将x传递给对象的正确想法;你还需要有一种方法可以在最后得出对象的计算结果 - 我相信你可以想出来;-)你在fib中使用的线程启动程序是就像你总是启动一个线程一样,(new Fib(x-1)).start()尽管你可能想要将线程保存在一个变量中,因为你需要它来获得稍后的计算结果。

答案 3 :(得分:1)

所以在你的帮助下,我设法做了同样的事情,实现runnable而不是使用Thread Class。

如果任务是实现runnable的话,你们都可以看看并告诉我这是怎么做的。 守则本身有效。

public class Fib implements Runnable
{
private int x;
public  int answer;

public Fib(int x) {
    this.x = x;
}

public void run() {
    if( x < 2 )
        answer = 1;
    else {
        try {
            Fib f1= new Fib(x-1);
            Fib f2= new Fib(x-2);
            Thread threadf1=new Thread(f1);
            Thread threadf2=new Thread(f2);
            threadf1.start();
            threadf2.start();
            threadf1.join();
            threadf2.join();

            answer = f1.answer + f2.answer;

        }
        catch(InterruptedException ex) { }
    }
}

public static void main(String[] args)

{
    try {

            for (int i=0;i<19;i++){
                Fib f= new Fib(i);
                Thread threadf= new Thread(f);
                threadf.start();
                threadf.join();

                System.out.println("Ergebnis:"+f.answer);

            }
        }

    catch(Exception e) {
        System.out.println("usage: java Fib NUMBER");
    }
  }
}