views:

256

answers:

6

Or is it?
I have a thread object from:

Thread myThread = new Thread(pObject);

Where pObject is an object of a class implementing the Runnable interface and then I have the start method called on the thread object like so:

myThread.start();

Now, my understanding is that when start() is called, the JVM implicitly (and immediately) calls the run() method which may be overridden (as it is in my case)

However, in my case, it appears that the start() method is not called immediately (as desired) but until the other statements/methods are completed from the calling block i.e. if I had a method after the start() call like so:

myThread.start();
doSomethingElse();

doSomthingElse() gets executed before the run() method is run at all.
Perhaps I am wrong with the initial premise that run() is always called right after the start() is called. Please help! The desired again is making executing run() right after start(). Thanks.

+9  A: 

run() is the first thing within your code that the new thread does, but there's some set-up work that the new thread does first, and there's no guarantee that any significant amount of work will by done by the new thread before the original thread goes on to call doSomethingElse().

You're right in thinking that there are no guarantees here. Making assumptions about the behaviour of multithreaded code is the source of much pain - try not to do it!

RichieHindle
+1 "Making assumptions about the behaviour of multithreaded code is the source of much pain - try not to do it!"
Yaneeve
+11  A: 

Um... the run() method will run in a different thread. That, per definition, means you cannot make any assumptions about before or after which statements in the current thread it will execute, unless you synchronize them explicitly.

Michael Borgwardt
+3  A: 

You've started a new thread. That thread runs in parallel to the thread that started it so the order could be:

pObject.run();
doSomethingElse();

or

doSomethingElse();
pObject.run();

or, more likely, there will be some crossover. pObject.run() may run in the middle of doSomethingElse() or vice versa or one will start before the other finishes and so on. It's important to understand this and understand what is meant by an atomic operation or you will find yourself with some really hard-to-find bugs.

It's even more complicated if two or more threads access the same variables. The value in one may never be updated in one thread under certain circumstances.

I highly suggest:

  1. You don't make your program multi-threaded unless you absolutely need to; and

  2. If you do, buy and read from cover to cover Brian Goetz's Java Concurrency in Practice.

cletus
+4  A: 

When you call myThread.start(), your thread becomes available for execution. Whether it will actually gain CPU, and for how long -- it's up the the OS scheduler. In fact, your run() may be getting control immediately, but losing it before it can do anything you can notice. The only way to ensure that your thread executes what you need before doSomethingElse() is to use explicit synchronization.

atzz
+1  A: 

To force your thread to run immediately (or to be more accurate, before doSomethingElse()), you need to do something like this

    java.util.concurrent.CountDownLatch latch = new CountdownLatch(1);
    new Thread(new MyRunnable(latch)).start();
    latch.await(); // waits until released by the child thread.
    doSomethingElse();

where

class MyRunnable implements Runnable {
    private CountDownLatch latch;
    MyRunnable (CountDownLatch latch) { this.latch = latch; }
    public void run() {
        doSomeStuff();
        latch.countDown(); // releases the parent thread
        doSomeMoreStuff();
    }
    ...
}

There are other ways to implement the synchronization using the concurrency classes, or Java's mutex / wait / notify primitives. But explicit synchronization between the two threads is the only way to guarantee the behavior that you require.

Note that the doSomething() call in the child thread will complete before the parent thread is released, but we can say nothing about the order of execution of doSomethingElese() and doSomeMoreStuff(). (One might run before the other and vice versa, or they might run in parallel.)

Stephen C
A: 

Stephen's suggestion sounds great, but may be limited to J2SE/J2EE. What if the java.util.concurrent libraries are not available as in J2ME, what would you suggest the user tried?

irenaeus