I don't completely understand how wait
and notify
(of Object
) work, and as a result I'm forced to slim down my attempts into the following section of code.
Main.java:
import java.util.ArrayList; class Main { public static Main main = null; public static int numRunners = 4; public static ArrayList<Runner> runners = null; public static void main(String[] args) { main = new Main(); } Main() { runners = new ArrayList<Runner>(numRunners); for (int i = 0; i < numRunners; i++) { Runner r = new Runner(); runners.add(r); new Thread(r).start(); } System.out.println("Runners ready."); notifyAll(); } }
Runner.java:
class Runner implements Runnable { public void run() { try { Main.main.wait(); } catch (InterruptedException e) {} System.out.println("Runner away!"); } }
Currently I get an IllegalMonitorStateException when calling Main.main.wait();
, but I don't understand why. From what I can see, I need to synchronize Runner.run
, but in doing so I assume it would only notify one thread, when the idea is to notify them all.
I've looked at java.util.concurrent
, but I can't find a suitable replacement (maybe I'm just missing something).
The IllegalMonitorStateException can be resolved by calling the wait() , notify() and notifyAll() methods after acquiring an object lock, i.e. within a synchronized block or method.
The wait() Method Simply put, calling wait() forces the current thread to wait until some other thread invokes notify() or notifyAll() on the same object. For this, the current thread must own the object's monitor.
The IllegalMonitorStateException is related to multithreading programming in Java. If we have a monitor we want to synchronize on, this exception is thrown to indicate that a thread tried to wait or to notify other threads waiting on that monitor, without owning it.
Simply put, wait() is an instance method that's used for thread synchronization. It can be called on any object, as it's defined right on java. lang. Object, but it can only be called from a synchronized block. It releases the lock on the object so that another thread can jump in and acquire a lock.
You can't wait()
on an object unless the current thread owns that object's monitor. To do that, you must synchronize
on it:
class Runner implements Runnable { public void run() { try { synchronized(Main.main) { Main.main.wait(); } } catch (InterruptedException e) {} System.out.println("Runner away!"); } }
The same rule applies to notify()
/notifyAll()
as well.
The Javadocs for wait()
mention this:
This method should only be called by a thread that is the owner of this object's monitor. See the
Throws:notify
method for a description of the ways in which a thread can become the owner of a monitor.
IllegalMonitorStateException
– if the current thread is not the owner of this object's monitor.
And from notify()
:
A thread becomes the owner of the object's monitor in one of three ways:
- By executing a synchronized instance method of that object.
- By executing the body of a
synchronized
statement that synchronizes on the object.- For objects of type
Class
, by executing a synchronized static method of that class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With