Home > Software design >  What specific Part of Java is causing this Thread to stay alive longer than the main Thread?
What specific Part of Java is causing this Thread to stay alive longer than the main Thread?

Time:10-20

I am just experimenting with Threads and I noticed something weird.

First I created this little class:

public class CustomThread implements Runnable{

    private String name;

    public CustomThread(String name){
        this.name = name;
    }

    @Override
    public void run() {
        for(int i = 0; i < 5; i  ){
            try {
                Thread.sleep(1000);
                System.out.println(name   " sleeping since "   (i 1)   " seconds");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println("Thread "   name   " ended.");
    }

}

In my main method I ran this:

Thread first = new Thread(new CustomThread("first"));
first.start();
Thread.sleep(5000);
System.out.println(first.isAlive());

Expected console output:

first sleeping since 1 seconds
first sleeping since 2 seconds
first sleeping since 3 seconds
first sleeping since 4 seconds
first sleeping since 5 seconds
Thread first ended.
false

Process finished with exit code 0

Actual console output every 10/10 times I tried this:

first sleeping since 1 seconds
first sleeping since 2 seconds
first sleeping since 3 seconds
first sleeping since 4 seconds
true
first sleeping since 5 seconds
Thread first ended.

Process finished with exit code 0

I thought, maybe it is because a Thread is taking some time to start up so that is why my customthread is taking longer. so I edited the code to wait until customthread has started like so:

Thread first = new Thread(new CustomThread("first"));
first.start();
while(!first.isAlive()){
    Thread.sleep(10);
}
Thread.sleep(5000);
System.out.println(first.isAlive());

But same console output everytime. Why?

CodePudding user response:

Just because you start a thread, there is no guarantee when exactly your CPU will execute the code associated with it. Even with your while loop, the thread alive flag may be set, but the runnable not yet even executed. In order to guarantee that your custom thread finishes before your main thread, you should join on your custom thread. That will eliminate any timing anomalies you might see with sleeping for a similar amount of time in both threads.

Thread first = new Thread(new CustomThread("first"));
first.start();
first.join();
System.out.println(first.isAlive());

CodePudding user response:

But same console output everytime. Why?

This is a classic thread race condition. A thread takes a little bit of time to start, stop, and have it's isAlive() value propagated. In my quick testing, setting the sleep in main to be 5020 meant that the output order was correct but isAlive() was still true. Setting it to 5040 got isAlive() to be false. This of course is dependent on my OS, thread support in my kernel, and what else is running on my computer. If you ran your program in a loop, I would expect that 5000 might work some of the time again because of race conditions in the threads.

It is the asynchronous nature of threaded programs which makes them powerful. The instant we expect things to happen in a certain order then we probably shouldn't be using threads.

As @JakeHenry mentioned, if you need to insure that your thread finishes at some point in main then you should call first.join(); instead of the sleep. The join() has the added feature of ensuring that any memory changes made by the first thread get propagated into the main thread too.

  • Related