3

I was trying to test/learn a few basic things in threading(Java) and came across a simple but confusing output. Following are my classes

public class CopyMaster implements Runnable{

    @Override
    public void run() {
        System.out.println("Run called from Copy Master for thread "+Thread.currentThread().getName());
    }

}

Main Class from where I am invoking threads

public class Main {

    public static void main(String[] args) {
        Thread[] threadArray = new Thread[4];
        for(int i=0; i<threadArray.length; i++){
            threadArray[i] = new Thread(new CopyMaster());
        }
        for(Thread t : threadArray){
            //[Line of intrest]System.out.println("Starting Thread "+t.getName());
            t.start();
        }
    }
}

OP(With Line of Interest un-commented)

Starting Thread Thread-0
Starting Thread Thread-1
Run called from Copy Master for thread Thread-0
Starting Thread Thread-2
Run called from Copy Master for thread Thread-1
Starting Thread Thread-3
Run called from Copy Master for thread Thread-2
Run called from Copy Master for thread Thread-3

OP(With Line of Interest commented)

Run called from Copy Master for thread Thread-2
Run called from Copy Master for thread Thread-3
Run called from Copy Master for thread Thread-0
Run called from Copy Master for thread Thread-1

I have tried running the code multiple times and observed that the sequence of print-outs are random in commented line of interest and in un-commented one its proper(in sequence)...

Why is it behaving like that?//EDITED as this confuses what i want to mean

EDIT:

I understand that threads behaves unpredictably but my main question is why it maintains oredr ALWAYS in one case and why random behavior is there in other case?

dev2d
  • 4,245
  • 3
  • 31
  • 54
  • 2
    Why do you think it should be in sequence? – Sotirios Delimanolis Jul 31 '14 at 04:54
  • Just run it a few more times. – Sotirios Delimanolis Jul 31 '14 at 04:59
  • @SotiriosDelimanolis - I think he needs to read the basics of concurrency before doing any coding. VD', please read this - http://docs.oracle.com/javase/tutorial/essential/concurrency/ – Erran Morad Jul 31 '14 at 04:59
  • main thread is executing sequencialy and where as other threads are running parallely, And parallel executions are always unpredictable. – Subhrajyoti Majumder Jul 31 '14 at 05:00
  • @SubhrajyotiMajumder i am not getting other printouts out-of-seq even..! – dev2d Jul 31 '14 at 05:04
  • 2
    Both Should be random. But when you uncomment the System.out statement, it take some CPU time to execute. It is highly probable the previous thread finish execution and the next thread is the only option to the dispatcher. I think that is why it seems in sequence. I you increase the number of threads you might see the changes in the sequence, or you can add a sleep statement in the run() method to check it. – naveejr Jul 31 '14 at 05:05
  • @naveejr you are 50% correct and actually gave answer to my question. :) One is always going to be sequential as it is running in main thread other changes when i increased size of thread array. – dev2d Jul 31 '14 at 05:07
  • @VD' Yes you are right, I 50% misunderstood the question. the [Line of Interest] is executing in the main thread (Single Thread). that is always in a sequence. – naveejr Jul 31 '14 at 05:12
  • Nobody seems to have answered your question which is, why does the println() call in the main thread cause the other threads to run in a _predictable_ order? I don't know for certain, but I'm guessing that the println() calls block the main thread: While main waits for its I/O to complete, the thread that it previously started gets a chance to run. Without the println() in main, the main thread may get to call start() four times before _any_ of the other threads gets a chance to run. At that point, the order in which the operating system picks them is unpredictable. – Solomon Slow Jul 31 '14 at 13:21

4 Answers4

2

This is precisely the behaviour of multithreading in Java, unpredictable.

for(Thread t : threadArray){
 //[Line of intrest]System.out.println("Starting Thread "+t.getName()); 

the above line runs in main thread --> so output is always in order (though other output lines can come in between)

t.start(); 

The above line starts each thread (prepares thread for execution, but the run method might not be called immediately). Nobody can predict which thread's run() will execute first. It is totally left to the JVM and underlying OS. }

If you want the output to be ordered, use join() to wait until other thread terminates.

EDIT :

OP(With Line of Interest un-commented)

Starting Thread Thread-0    --> executed in main thread --> 0--> in order
Starting Thread Thread-1   --> main thread --> 1 --> in order
Run called from Copy Master for thread Thread-0 --> executed in thread-0.
Starting Thread Thread-2    --> executed in main. --> 2 -> in order
Run called from Copy Master for thread Thread-1 --> executed in thread-1
Starting Thread Thread-3 --> main --> 3 --> in order
Run called from Copy Master for thread Thread-2 -->executed in thread-2.
Run called from Copy Master for thread Thread-3 --> executed in thread-3.

Note : Starting Thread Thread-0 is printed in the main thread. So, the next line thread.start() might not even have been executed. The logs are misleading.

The below lines actually suggest how threads ran. These logs aren't misleading.

OP(With Line of Interest commented)

Run called from Copy Master for thread Thread-2
Run called from Copy Master for thread Thread-3
Run called from Copy Master for thread Thread-0
Run called from Copy Master for thread Thread-1
TheLostMind
  • 35,966
  • 12
  • 68
  • 104
  • agree, and i understand the same but my question is with Line of interest un commented why it follows order?? – dev2d Jul 31 '14 at 04:55
  • 1
    @VD' - try to make each thread sleep before commented line. Run this code a few times and tell us what you see. – Erran Morad Jul 31 '14 at 04:58
  • 1
    @VD' - No. Even if you comment *line of interest*, it makes no difference whatsoever. The line of difference runs in the *main thread* (see my answer). Both in *commented and uncommented* situations the `run()` method are executed out of order. – TheLostMind Jul 31 '14 at 04:58
  • @TheLostMind Correct me if i am not understanding your answer but you mean to say whatever is running in main thread will be sequential but then other statements in CopyMaster should be out of sequence some time.. I tried a lot of time but they are also in seq – dev2d Jul 31 '14 at 05:01
  • @VD' - No, the lines of statements appearing in main thread run *as-is* or sequentially. but other threads execution can interleave with `main` threads execution. In your logs (check my edited answer), the lines `starting thread thread-X` are always sequential in *main*. i.e, you always get` 0,1,2,3...` – TheLostMind Jul 31 '14 at 05:07
  • 2
    accepting your answer you and naveejr(in question comments) helped me understand this. the thing is as you said main thread is always seq but other can be random which i verified increasing thread array size – dev2d Jul 31 '14 at 05:09
2

Thread interleaving is not random (in the sense of a uniform random number generator), but unpredictable.

In this particular case, the sequential execution if the main thread prints is probably caused by all involved threads writing to System.out, whose methods are synchronized. Therefore, only one thread can write to the console at any given time (which is why we see interleaving of lines rather than individual characters), while the other threads wanting to print wait in a queue until the other thread has exit the monitor. Apparently, the JVM implementation you use ensures that the threads enter the monitor in the same order the have entered that queue, which being the first action in the worker threads, happens very soon after they have started, and therefore in the same order.

Put differently, in this particular program, the heavy lock contention, on this particular JVM implementation, on this operating system, causes the threads to executed in a particular order with high probability. On other JVM implementations, other operating systems, or even slightly modified programs, the behavior may be totally different. Therefore, you should not assume a particular order, even if your tests never observe a different ordering.

meriton
  • 68,356
  • 14
  • 108
  • 175
  • +1 for investing answer. Does that mean that a main thread can also some time be unpredictable and can give non sequential output?? – dev2d Jul 31 '14 at 09:14
0

Its because there is no guarantee that a thread runs immediately after it starts in your case. You have to synchronize it explictly.

Look at Why is run() not immediately called when start() called on a thread object in java

Community
  • 1
  • 1
thePoly_glot
  • 135
  • 1
  • 2
  • 11
  • That's becuase some amount of work is done in //[Line of intrest]System.out.println("Starting Thread "+t.getName()); I wouldn;t trust this behavior. Put it in a loop and see if your line of interest is really interesting or not. :-) – thePoly_glot Jul 31 '14 at 05:02
0

Sometimes thread can produce different output. This is because we don't know which thread is running at which moment in time. It is based on JVM so it is unpredictable.