views:

128

answers:

5

Hello All...

Recently I have gone through with one simple threading program, which leads me some issues for the related concepts... My sample program code looks like :

class NewThread implements Runnable {
    Thread t;
    NewThread() {
        t = new Thread(this, "Demo Thread");
        System.out.println("Child thread: " + t);
        t.start(); // Start the thread
    }
    public void run() {
        try {
            for (int i = 5; i > 0; i--) {
                System.out.println("Child Thread: " + i);
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            System.out.println("Child interrupted.");
        }
        System.out.println("Exiting child thread.");
    }
}
class ThreadDemo {
    public static void main(String args[]) {
        new NewThread(); // create a new thread
        try {
            for (int i = 5; i > 0; i--) {
                System.out.println("Main Thread: " + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("Main thread interrupted.");
        }
        System.out.println("Main thread exiting.");
    }
}

Now this program giving me the output as follows :

Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.

So, that's very much clear to me. But as soon as I am replacing the object creation code (calling of a NewThread class constructor) to as follows :

NewThread nt = new NewThread(); // create a new thread

the output becomes a bit varied like as follows :

Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Child Thread: 3
Main Thread: 4
Child Thread: 2
Child Thread: 1
Main Thread: 3
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.

And some times it's giving me same output in both the cases. So, i am not getting the exact change in both the scenario.

I would like to know that you the variation in the output is coming here ?

Thanks in advance...

A: 

Are both outputs correct for both programs? Yes.

The answer is the output is undefined. The particular (correct) output you get each time could depend on just about anything, including minor variations in the compiled bytecode. (It might be worth checking this with javap -c, just to be sure the difference in code is a possible cause.)

In general if you have two threads doing things in parallel, you can't be sure of the ordering of their combined output unless you synchronise them somehow.

Edmund
This has nothing to do with the bytecode, which is all but identical. It has everything to do with threads swapping in/out at different times.
Sean Owen
The poster claimed that the two versions had different behaviour. I did not say bytecode was solely responsible; I said it could influence the relative likelihood of outputs. Mostly I said, take a look at it to verify that it is different.
Edmund
+5  A: 

The changed output is due to nature of both OS process scheduling and JVM thread scheduling. Even if you take out the second thread there is no guarantee that your thread will wake-up exactly after 500ms.

Tahir Akhtar
+2  A: 

I'm not sure I understand the change that you mention, but the scheduling is non-deterministic, i.e., it may schedule the threads differently in different runs of the application.

Another thing; creating and starting a new thread in the constructor isn't really best practice. Have you considered letting NewThread extend Thread? Like this:

class NewThread extends Thread {
    NewThread(String str) {
        super(str);
        System.out.println("Child thread: " + this);
    }
    public void run() {
        try {
            for (int i = 5; i > 0; i--) {
                System.out.println("Child Thread: " + i);
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            System.out.println("Child interrupted.");
        }
        System.out.println("Exiting child thread.");
    }
}

public class ThreadDemo {
    public static void main(String args[]) {
        new NewThread("Demo Thread").start();
        try {
            for (int i = 5; i > 0; i--) {
                System.out.println("Main Thread: " + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("Main thread interrupted.");
        }
        System.out.println("Main thread exiting.");
    }
}
aioobe
It's generally better to just implement Runnable than extend Thread, then you don't mix the responsibilities.
Pete Kirkham
A: 

You have two threads, one which does something about every half second, one which does something about every second.

The JVM and OS makes no guarantee which of the threads available for scheduling gets run at a given time. Alternatively, if you have multiple cores then both threads could be running at the same time, and competing for a lock on the System.out that stops two threads printing at the same time - if you send the output one character at a time instead of using println, then the characters from both thread's output might be mixed together.

Your output shows that at one second and at two seconds, which of the two threads prints its output it is not predictable. This is as expected.

It makes no difference in this case whether or not you assign the NewThread object to a local variable. The object is not eligible for garbage collection while the thread it is running in is running (assuming Threads hold a reference to their runnable), and nothing else uses the local variable. So the difference after that change in the code is just the randomness in the scheduling, not the effect of the change.

Pete Kirkham
A: 

As mentioned above, this is normal behaviour. If you need some tasks started at a specific time and/or at a fixed interval, then the Timer's scheduleAtFixedRate() may give you a better result.

Indrek