简体   繁体   中英

Thread.start() doesn't call Thread.run() method

In my projects there're 3 classes that extends Thread, each of them does some calculation for integer number. I need to run them to get all three calculated values. This process needs to be done for all integers in a certain range.

This's one of my threads:

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));
}
}

That's a method that tries to start threads:

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();

    }
}

After running my code I get this:

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

As I understand, start() does not call run() method. In my run method there's sleep(500), but the result just appears in console without any sleep.

I would appreciate any help, as I've spent too much time on this stuff already and unfortunately didn't solve the problem.

There are a couple of things going on here which will confuse you. Let's start with something that isn't obvious:

System.out.print() uses locking to make sure threads don't print over each other. So when you have two threads and one prints foo and the other prints bar , you can get either foobar or barfoo but never fboaro (= no mixing).

That also means when one thread (the main or one of your three calculation threads) prints something, all other threads that also want to print a the same time, will wait.

Next: Starting threads doesn't queue them. If you start N threads, the system will run all the code of them at the same time. If they all sleep 500ms, then this sleeping will haven in parallel. If you want threads to execute in a certain order, you must use queues and locks.

Lastly: You start the threads but you never wait for the results. So what happens is that the main thread starts the threads and then continues (probably terminates). Then all three threads wait for 500ms at the same time and then they all try to calculate the result and print it at the same time.

As you probably begin to understand, all this is pretty complex and annoying. That's why Java 6 introduced the concurrent framework which solves many of these problems.

In a nutshell, don't create threads anymore. Create Callables which return the result you want and then submit them to an ExecutorService . The service will run them and return Future s. You can then query the future for a result.

This way, you don't have to deal with low-level threading issues, synchronization, locks and queues.

Related:

(Edit to allow to remove downvote.)

Your results are hidden probably in the last String: "true2hi6falsetrue5hi2483falsehi720hi120". All the Threads execute actually the command:

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

when the loop has ended bacause they have to wait 0,5 seconds. You have also a print method to do this, not a println , therefore each result is "sticked" to another. As the comments indicate, threads are not excecuted individually, they do not wait namely the end of the previous Thread .

And one moore thing you need to do: wait for the threads to finish. I would expect three calls of Thread.join() otherwise your program might end and abort the threads (you did mot mark them as daemon, right?) before they're able to print the result.

Thanks all of you! It helped me to understand threads better. To solve the problem I used method join(), so now the method that starts threads looks like this:

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();
    }
}

and my thread classes I didn't change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM