简体   繁体   中英

What is the reason behind this behaviour(Thread)

I was working on Threads and decided to add some extra text before and after my focused lines of code are run, for reference. I expected to get one 'extra-text' towards the start and the other at the end. However... that's not happening and the second 'extra-text' just comes at the fourth position when I run it. I am a beginner and need to know why this is happening...

---CODE---

class Hi extends Thread{

    public void run(){
        for(int i=1; i<=5; i++){
            System.out.println("HI!");
            try{
                Thread.sleep(500);
            } catch(InterruptedException e){}

        }
    }

}


class Hey extends Thread{
    public void run(){
        for(int i=1; i<=5; i++){
            System.out.println("HEY!");
            try{
                Thread.sleep(500);
            } catch(InterruptedException e){}

        }
    }

}

public class MyClass {

    public static void main(String[] args){

        Hi hiObj = new Hi();
        Hey heyObj = new Hey();

        System.out.println("extra-text");

        hiObj.start();
        heyObj.start();

        try {
            Thread.currentThread().sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("extra-text");

    }



}

---OUTPUT---

extra-text
HI!
HEY!
extra-text
HEY!
HI!
HEY!
HI!
HEY!
HI!
HEY!
HI!

This is a common concurrency error.

The main method of your program runs on the main thread. Thus, before you've started the hiObj and heyObj threads, you already have one thread. After you start both of the new threads, you have three. Each executes concurrently. This means that each thread can execute code without waiting for the others. Order is not guaranteed between threads.

This causes the behavior you observe. Before hiObj or heyObj are started, the main method running on the main thread prints "extra-text" . Next, hiObj and heyObj are started. The main thread reaches the line Thread.currentThead().sleep(10) which causes it to suspend execution for 10 milliseconds. On most machines (including yours), this is enough time for the other two threads to begin execution. Each thread begins the for loop in its run method and prints either "HI" or "HEY" . Thus, the first three lines of output are (the order of "HI" and "HEY" are not guaranteed):

"extra-text"

"HI"

"HEY"

Next, the hiObj and heyObj threads reach the line Thread.sleep(500) which causes them to suspend execution for 500 milliseconds. After 10 milliseconds have passed, the main thread will be finished sleeping a will resume. Note that neither the hiObj or heyObj threads could have resumed by now. Thus, the next line printed will be the from the next line executed in main . This is "extra-text" . Thus, the expected output is:

"extra-text"

"HI"

"HEY"

"extra-text"

Over the next few seconds, the remaining prints from the hiObj and heyObj threads will occur. In Java, the main thread exits only after all other threads have exited (unless System.exit is called or there is an uncaught exception). In this case this means the program will only exit when main reaches the end of execution and when both hiObj 's and heyObj 's run methods return.

To change your program so that the last "extra-text" always prints at the end, you have to cause the main thread to wait for the hiObj and heyObj threads to finish. In Java, there is a method on Thead called join which causes the calling thread to wait until the joined thread dies. In your program, you can modify MyClass to look like this:

public class MyClass {

    public static void main(String[] args){

        Hi hiObj = new Hi();
        Hey heyObj = new Hey();

        System.out.println("extra-text");

        hiObj.start();
        heyObj.start();

        try {
            Thread.currentThread().sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        hiObj.join();
        heyObj.join();

        System.out.println("extra-text");

    }

}

With this change, main will first wait for hiObj to finish and then wait for heyObj to finish before it prints "extra-text" .

If you get rid of the

Thread.currentThread().sleep(10);

in the main Method you will see that your two extra texts are printed to the console immediately after execution. By using the sleep(10) you just delay the second extra text and in the meantime your 2 threads print their first output.

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