0

At some point in my application, I want to put my main thread (ie., the currently executing thread) to sleep for some time or until the background has finished (and wakes it up), whichever comes first.

Here is what I did (which I thought would work, but didn't)

public static void main(String args[])
{
    // .... other stuff ...

    // show a splash screen
    // just think of this as an image
    showPlashScreen(): 
    new Thread(new Runnable()
    {
          public void run()
          {
                // do some work here

                // notify everyone after the work is done
                Thread.currentThread().notifyAll();
          }
    }).start();

    // now make the current thread to wait for the background
    // or for at most 1000
    Thread.currentThread().wait(1000);
    disposeSplashScreen();

    // ... other stuff ....
}

Executing this, I keep getting java.lang.IllegalMonitorStateException

(Partial) stacktrace:

Caused by: java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)

.... <cut> ....

Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
One Two Three
  • 22,327
  • 24
  • 73
  • 114

4 Answers4

5

To be able to call notify() you need to synchronize on the same object.

synchronized (someObject) {
    someObject.wait();
}

/* different thread / object */
synchronized (someObject) {
    someObject.notify();
}
SeniorJD
  • 6,946
  • 4
  • 36
  • 53
  • This works for me! But would you mind explaing how it works? So in the first sync-block, when `someObject.wait()` is executed, the current thread would go to sleep (do nothing), right? That would mean the sync-block does not finish executing yet. As a result, `someObject` will be aquicred by the current thread (forever)! How can the second sync-block ever acquire `someObject` so it can call `notify` on it? (I'm pretty sure I got something wrong above, could you please point it out? Thanks!) – One Two Three May 01 '13 at 07:30
  • 1
    That's simple. As soon the monitor ( `someObject` ) owner thread reaches the `wait` method, it stops to be an owner, the lock is released and the thread starts to sleep until the `notify` method called. – SeniorJD May 01 '13 at 07:43
2

Firstly, don't use wait and notify on Thread objects. That's used as an internal signalling channel, so your code can end up confusing the JRE code and vice versa.

Secondly, one reason it's not working is that your main thread is waiting on itself, and the background thread is notifying itself - those are different objects!

Thirdly, to use notify() and wait() you need to synchronize on the monitor first. Also, for wait you'd generally use a loop to check for a condition, to handle spurious wakeups.

Fourthly, if you're really waiting for a thread to end, you can just use join instead:

Thread thread = new Thread(new Runnable()
{
    @Override public void run()
    {
        // do some work here
    }
});
thread.start();

// Do something else

thread.join(1000);

(Unfortunately join doesn't indicate whether or not it returned due to a timeout or the thread completing - but you can check for the thread state afterwards.)

Alternatively, use one of the higher-level constructs in java.util.concurrent instead - they're generally less fiddly, as JB Nizet suggested.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Please see [This link](http://stackoverflow.com/questions/16219111/cant-transparent-and-undecorated-jframe-in-jdk7-when-enabling-nimbus) – Azad May 01 '13 at 06:58
1

You're using two different objects for wait() and notifyAll() : the main thread waits on the main thread, whereas the background thread notifies on the background thread. You should use a shared, final object for the two calls. You should also wait and notify in a synchronized block on this shared object, as explained in the javadoc of those two methods. And there should only exit from the waiting state where some condition has changed, to avoid spurious wakeups, as explained in the javadoc.

But wait() and notifyAll() are too low-level and too hard to use correctly. You should use a higher-level abstraction like a Semaphore instead.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

As you want to put the current thread to sleep while waiting for another thread, the way you are doing it as of now is not meant for the same thing i.e. wait and notifiy methods.

These methods are meant to be used for Synchronized Objects not for thread.

For Threads you should use join method. Check Out

gprathour
  • 14,813
  • 5
  • 66
  • 90