I am using multi-threading in java for my program.
I have run thread successfully but when I am using Thread.wait()
, it is throwing java.lang.IllegalMonitorStateException
.
How can I make a thread wait until it will be notified?
views:
453answers:
5You need to be in a synchronized
block in order for Object.wait() to work.
Also, I recommend looking at the concurrency packages instead of the old school threading packages. They are safer and way easier to work with.
Happy coding.
EDIT
I assumed you meant Object.wait() as your exception is what happens when you try to gain access without holding the objects lock.
Since you haven't posted code, we're kind of working in the dark. What are the details of the exception?
Are you calling Thread.wait() from within the thread, or outside it?
I ask this because according to the javadoc for IllegalMonitorStateException, it is:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
To clarify this answer, this call to wait on a thread also throws IllegalMonitorStateException, despite being called from within a synchronized block:
private static final class Lock { }
private final Object lock = new Lock();
@Test
public void testRun() {
ThreadWorker worker = new ThreadWorker();
System.out.println ("Starting worker");
worker.start();
System.out.println ("Worker started - telling it to wait");
try {
synchronized (lock) {
worker.wait();
}
} catch (InterruptedException e1) {
String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
System.out.println (msg);
e1.printStackTrace();
System.out.flush();
}
System.out.println ("Worker done waiting, we're now waiting for it by joining");
try {
worker.join();
} catch (InterruptedException ex) { }
}
wait
is defined in Object
not Thread
. The monitor on Thread
is a little unpredictable.
Although all Java objects have monitors, it generally better to have a dedicated lock:
private final Object lock = new Object();
You can get slightly easier to read diagnostics, at a small memory cost (about 2K per process) by using a named class:
private static final class Lock { }
private final Object lock = new Lock();
In order to wait
or notify
/notifyAll
an object, you need to be holding the lock with the synchronized
statement. Also, you will need a while
loop to check for the wakeup condition (find a good text on threading to explain why).
synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}
To notify:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
It is well worth getting to understand both Java language and java.util.concurrent.locks
locks (and java.util.concurrent.atomic
) when getting into multithreading. But use java.util.concurrent
data structures whenever you can.
Thread.wait() call make sense inside a code that synchronizes on Thread.class object. I don't think it's what you meant.
You ask
How can I make a thread wait until it will be notified?
You can make only your current thread wait. Any other thread can be only gently asked to wait, if it agree.
If you want to wait for some condition, you need a lock object - Thread.class object is a very bad choice - it is a singleton AFAIK so synchronizing on it (except for Thread static methods) is dangerous.
Details for synchronization and waiting are already explained by Tom Hawtin.
java.lang.IllegalMonitorStateException
means you are trying to wait on object on which you are not synchronized - it's illegal to do so.
Based on your comments it sounds like you are doing something like this:
Thread thread = new Thread(new Runnable(){
public void run() { // do stuff }});
thread.start();
...
thread.wait();
There are two problems. First, as others have said, obj.wait()
can only be called if the current thread holds the primitive mutex for obj
. If the current thread does not hold the mutex, you get the exception you are seeing.
The second (more important) problem is that thread.wait()
does not do what you seem to be expecting it to do. Specifically, thread.wait()
does not cause the nominated thread to wait. Rather it causes the current thread to wait until some other thread calls thread.notify()
or thread.notifyAll()
.
There is actually no safe way to force a Thread instance to pause if it doesn't want to. (The nearest that Java has to this is the deprecated Thread.suspend()
method, but that method is inherently unsafe, as is explained in the Javadoc.)
If you want the newly started Thread to pause, the best way to do it is to create a CountdownLatch instance and have the thread call await()
on the latch to pause itself. The main thread would then call countDown()
on the latch to let the paused thread continue.