0

在我的项目中,有 3 个类扩展了 Thread,每个类都对整数进行一些计算。我需要运行它们以获取所有三个计算值。这个过程需要对一定范围内的所有整数进行。

这是我的主题之一:

public class FactorialNumber extends Thread {
private int number;

public void setNumber(int number) {
    this.number = number;
}

public void run() {
    try {
        sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace(); 
    }
    System.out.print(NumbersOperations.getFactorial(number));
}
}

这是一种尝试启动线程的方法:

public static void getThreevalues() throws InterruptedException {
    int startOfRange = getBorder("Enter the left border of range: ");
    int endOfRange = getBorder("Enter the right border of range: ");
    for(int i = startOfRange; i <= endOfRange; i++) {
        PrimeNumber primeNumber = new PrimeNumber();
        FibonachiNumber fibonachiNumber = new FibonachiNumber();
        FactorialNumber factorialNumber = new FactorialNumber();
        primeNumber.setNumber(i);
        fibonachiNumber.setNumber(i);
        factorialNumber.setNumber(i);
        System.out.print("Number: " + i);
        System.out.print(" is prime number ");
        primeNumber.start();
        System.out.print(". Fibonachi - " );
        fibonachiNumber.start();
        System.out.print(". Factorial - ");
        factorialNumber.start();
        System.out.println();

    }
}

运行我的代码后,我得到了这个:

Number: 3 is prime number . Fibonachi - . Factorial - 
Number: 4 is prime number . Fibonachi - . Factorial - 
Number: 5 is prime number . Fibonachi - . Factorial - 
Number: 6 is prime number . Fibonachi - . Factorial - 
true2hi6falsetrue5hi2483falsehi720hi120

据我了解, start() 不调用 run() 方法。在我的运行方法中有sleep(500),但结果只是出现在控制台中,没有任何睡眠。

我会很感激任何帮助,因为我已经在这些东西上花费了太多时间,不幸的是没有解决问题。

4

4 回答 4

5

这里有几件事会让你感到困惑。让我们从不明显的东西开始:

System.out.print()使用锁定来确保线程不会相互打印。因此,当您有两个线程和一个 printsfoo和另一个 printsbar时,您可以获得foobarbarfoo但永远不会fboaro(= 不混合)。

这也意味着当一个线程(主线程或三个计算线程之一)打印某些内容时,所有其他也想同时打印的线程将等待。

Next: 启动线程不会将它们排队。如果启动 N 个线程,系统将同时运行它们的所有代码。如果他们都睡了 500 毫秒,那么这个睡眠将并行。如果您希望线程按特定顺序执行,则必须使用队列和锁。

最后:您启动线程,但您从不等待结果。所以发生的是主线程启动线程然后继续(可能终止)。然后三个线程同时等待500ms,然后他们都尝试计算结果并同时打印。

正如您可能开始理解的那样,所有这些都非常复杂且令人讨厌。这就是为什么 Java 6 引入了解决许多这些问题的并发框架。

简而言之,不要再创建线程了。创建Callables哪个返​​回您想要的结果,然后将它们提交到ExecutorService. 该服务将运行它们并返回Futures。然后,您可以查询未来的结果。

这样,您就不必处理低级线程问题、同步、锁和队列。

有关的:

(编辑以允许删除downvote。)

于 2013-08-29T14:38:48.957 回答
0

感谢大家!它帮助我更好地理解线程。为了解决这个问题,我使用了join()方法,所以现在启动线程的方法是这样的:

public static void getThreevalues() throws InterruptedException {
    int startOfRange = getBorder("Enter the left border of range: ");
    int endOfRange = getBorder("Enter the right border of range: ");
    for(int i = startOfRange; i <= endOfRange; i++) {
        PrimeNumber primeNumber = new PrimeNumber();
        FibonachiNumber fibonachiNumber = new FibonachiNumber();
        FactorialNumber factorialNumber = new FactorialNumber();
        primeNumber.setNumber(i);
        fibonachiNumber.setNumber(i);
        factorialNumber.setNumber(i);
        System.out.print("Number: " + i);
        primeNumber.start();
        primeNumber.join();
        fibonachiNumber.start();
        fibonachiNumber.join();
        factorialNumber.start();
        factorialNumber.join();
        Thread.sleep(2000); // this line's useful to present result by lines
        System.out.println();
    }
}

我的线程类我没有改变。

于 2013-08-30T10:36:55.637 回答
0

您的结果可能隐藏在最后一个字符串中:“true2hi6falsetrue5hi2483falsehi720hi120”。所有线程实际上执行命令:

System.out.print(NumbersOperations.getFactorial(number)); 

当循环结束时,他们必须等待 0.5 秒。您还有一种print方法可以做到这一点,而不是 a println,因此每个结果都“粘”到另一个结果上。正如评论所示,线程不会单独执行,它们不会等待前一个的结束Thread

于 2013-08-29T14:25:17.637 回答
0

您还需要做一件事:等待线程完成。我预计三个调用,Thread.join()否则您的程序可能会在它们能够打印结果之前结束并中止线程(您确实将它们标记为守护进程,对吗?)。

于 2013-08-29T17:39:48.967 回答