Reputation: 23497
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)
Upvotes: 0
Views: 8286
Reputation: 15333
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
Upvotes: 0
Reputation: 7202
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();
}
Upvotes: 5
Reputation: 691685
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.
Upvotes: 1
Reputation: 1500225
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.
Upvotes: 2