Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question on Java Thread, output consistent

In the below code the answer is always Started 0 1 2 3 Complete. Im just wondering how it is possible.

If someone could help with the consistency of the output, it would be nice

public class TestOne extends Thread {

/**
 * @param args
 */
public static void main(String[] args)throws Exception {
    // TODO Auto-generated method stub

    Thread t = new Thread(new TestOne());
    t.start();
    System.out.println("started");
    t.join();
    System.out.println("Complete");




}

public void run(){
    for(int i=0;i<4;i++){
        System.out.println(i);
    }
}
like image 358
randeepsp Avatar asked Jun 09 '11 05:06

randeepsp


2 Answers

Most likely you're getting the same results because, most of the time, the main thread starts a new thread then, before that new thread has a chance to print anything, the main thread prints its started message. The join in the main thread then forces it to wait until the other thread has finished, then it prints Complete.

You have a race condition here. The instant you start the second thread, it's indeterministic as to which order the lines will be output (other than the complete line which is made deterministic by virtue of the wait call, as previously mentioned).

But a race condition doesn't guarantee that you'll get different results on multiple runs, only that it is possible. You still shouldn't rely on that behaviour, of course.

For example, the following code:

public class TestOne extends Thread {
    public static void main (String[] args) throws Exception {
        Thread t = new Thread (new TestOne());
        t.start();

        Thread.sleep (1000);  // <- Added this.

        System.out.println ("Started");
        t.join();
        System.out.println ("Complete");
    }

    public void run() {
        for (int i = 0; i < 4; i++) {
            System.out.println (i);
        }
    }
}

will output:

0
1
2
3
Started
Complete

Although, even then, the order is not guaranteed as it may take more than a second for the thread to "warm up" - sleep is rarely a good solution to race conditions. I've just used it here for illustrative purposes.

like image 75
paxdiablo Avatar answered Oct 04 '22 19:10

paxdiablo


When you say Thread t = new Thread(); nothing special happens because you are not creating a "Thread" per se. It is just an object that has the "characteristics" to become a thread of execution. For the object to be a "Thread" you have to call t.start(); and this is where the magic lies.

When you say t.start() the JVM creates a new stack for the newly created thread to run. It associates that stack to the thread object in question. And then makes it available for scheduling. Basically this means that it queues the thread in the JVM scheduler and in the next time slice it is also available for execution. The JVM actually does a lot more than this, my answer is just oversimplified for your example.

Invariably, meanwhile all these thread + stack creation, your main thread has the opportunity to move to its next instruction which in your case is System.out.println("started");.

Theoretically, what you say is true, "Started" could come anywhere in between 0, 1, 2, 3. However in reality, since your t.start() is an "expensive" method, it takes some time to complete, during which the main thread generally gets the chance to execute its next instruction.

If you want to know the details of t.start(); look into the Java source code.

like image 31
Swaranga Sarma Avatar answered Oct 04 '22 18:10

Swaranga Sarma