views:

84

answers:

4
public class Test extends Thread{
    public void hello(String s){
     System.out.println(s);
    }
    public void run(){
     hello("I’mrunning...");
    }//endofrun()
    public static void main(String [] args){
     Test t=new Test();
    System.out.println("always first");
     t.start();

     System.out.println("always second but why?");
    } 
}

I've run that chunk of code 30 times.

Why is "always second but why?" always second on the console? When t.start() is called, we have 2 threads. (2 stacks): the main thread and the second thread. so "i'am running" has to be sometimes the second output on the console. When i delete the "always first" output statement than the two outputs left, behave non deterministic (that's the way it should be)

so what is wrong in my thinking, why is System.out.println("always first"); influencing the concurrency?

+5  A: 

By writing something out to the console first, you may well be affecting when JIT compilation occurs and possibly even type initialization occurs. I don't find it completely unbelievable that something like this changes the observed ordering. I wouldn't be surprised to see the program behave slightly differently on different systems and with different JVMs.

The thing is, either of those orderings is completely valid. You shouldn't rely on it being one or the other, and it's not a bug if it always happens the same way. (Or rather, it might be - but it doesn't have to be.)

If you want to ensure a particular order, you need to do that explicitly - if you don't mind what order things happen in, then there's no problem :)

Jon Skeet
Of course, deterministic behaviour makes testing more difficult...
Tom Hawtin - tackline
A: 

System.out.println("always first") will always come first, because it comes before the 2nd thread starts, so it will never effect the concurrency.

try placing "always first" sentence after t.start();, you may get what you're expecting :)

evilReiko
+1  A: 

I've run that chunk of code 30 times.

Run it another seven billion times on every OS and hardware combination possible and report your findings then. 30 is a very low value of forever.

Why is "always second but why?" always second on the console?

How many cores do you have? Most thread schedulers will favour the currently running thread over a newly spawned one, especially on single cores, and will favour synchronizing threads between cores at as late a point as possible (the thread object and System.out needs to be passed between the OS threads).

Given threading is not deterministic and most OS don't guarantee fairness nor timeliness, it's not in any way a bug that it behaves in this way.

If you want an explicit ordering between the threads, then you should use either syncronized blocks or the more powerful classes in java.util.concurrent. If you want non-deterministic behaviour, but to allow the other thread to run, you can give a hint to the scheduler using Thread.yield().

public static void main ( String [] args ) 
{
    FirstThreadBug t = new FirstThreadBug();
    System.out.println ( "always first" );
    t.start();
    yield();
    System.out.println ( "always second but why?" );
}
Pete Kirkham
A: 

Why is "always second but why?" always second on the console?

It's not always second. I managed to produce both orderings in about 5 executions of your code. Both orderings are valid, and thread scheduling depends on your OS, and possibly JVM and hardware as well.

so what is wrong in my thinking, why is System.out.println("always first"); influencing the concurrency?

Your thinking is right, your experiments are misleading you ;)

Tuure Laurinolli