Why don't threads run consistently?

211 views Asked by At

I am playing around with multithreading and came across an inconsistency when running a small snippet of code. The following code should print out 123123... but what I'm getting is

class RunnableDemo implements Runnable {
    private String message;

    RunnableDemo(String m) {
        message = m;
    }

    public void run() {
        try {
            for (int i = 0; i < message.length(); i++) {
                System.out.print(message.charAt(i));
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

public class TestThread {
    public static void main(String args[]) throws InterruptedException {

        new Thread(new RunnableDemo("1111111")).start();
        new Thread(new RunnableDemo("2222222")).start();
        new Thread(new RunnableDemo("3333333")).start();

    }
}

Output: 123231231132123231321

Output: 123213123123213213213

Output: 123231213213231231213

What I don't get is that it run correctly the first pass through (prints '123') but then the second pass through it prints '231'. If the thread is printing a char, sleeping 1 second, then repeating. Shouldn't the pattern 123123... be consistent each time I run the code or at least follow the pattern of the first 3 chars?

2

There are 2 answers

1
Jon Skeet On BEST ANSWER

The following code should print out 123123

Not necessarily. You should basically never rely on threads with no synchronization between them happening to wake up and execute in any particular order.

Let's take the very first character output: there's no guarantee that that will be 1. Yes, you're starting the thread printing 1 first, but that doesn't mean that's the first thread that will actually start executing run first - or even if it does, that doesn't mean that's the first thread that will get as far as the System.out.print call.

Given the fairly long sleep, I would expect (but ideally not rely on) the output being a sequence of 7 "chunks", where each "chunk" consists of the characters "123" in some permutation. But if you've got three threads which all go to sleep for a second at "roughly" the same time, you shouldn't expect them to necessarily wake up in the order 1, 2, 3 - and again, even if they do, one of them may pre-empt another within the loop body.

On a really, really slow machine, even that expectation would be invalid - imagine it takes a random amount of time between 0 and 20 seconds to call charAt - unlikely, but it's a feasible thought experiment. At that point, one of the threads could race ahead and finish its output before another of the threads managed to print anything.

Threads are designed to be independent - if you want them to work in a coordinated fashion, you have to specify that coordination yourself. There are plenty of tools for the job, but don't expect it to happen magically.

0
Fahad Siddiqui On

You can't predict what piece of program CPU runs at a time. While running some process the CPU converts the process into small pieces of work. As multiple processes are running at a time. CPU has to schedule according to scheduling algorithm implemented. So, in short, you cannot predict what CPU does next unless you programmatically synchronize the pieces of code.