Java等待并通知:IllegalMonitorStateException
我不完全了解wait
和notify
( Object
)的工作,结果我不得不削减我的尝试到下面的代码段。
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!"); } }
目前,我调用Main.main.wait();
时,我得到一个IllegalMonitorStateException Main.main.wait();
,但我不明白为什么。 从我所能看到的,我需要同步Runner.run
,但是这样做,我认为它只会通知一个线程,当想法是通知他们所有。
我已经看了java.util.concurrent
,但我找不到合适的replace(也许我只是缺less一些东西)。
除非当前线程拥有该对象的监视器,否则不能wait()
对象wait()
。 要做到这一点,你必须synchronize
:
class Runner implements Runnable { public void run() { try { synchronized(Main.main) { Main.main.wait(); } } catch (InterruptedException e) {} System.out.println("Runner away!"); } }
同样的规则也适用于notify()
/ notifyAll()
。
wait()
的Javadocs提到了这个:
这个方法只能由这个对象监视器的所有者的线程调用。 有关线程可以成为监视器所有者的方式的说明,请参阅
notify
方法。抛出:
IllegalMonitorStateException
– 如果当前线程不是此对象监视器的所有者。
并从notify()
:
线程以三种方式之一成为对象监视器的所有者:
- 通过执行该对象的同步实例方法。
- 通过执行同步对象的
synchronized
语句的主体。- 对于types为
Class
对象,通过执行该类的同步静态方法。
您正在调用wait
和notifyAll
而不使用synchronized
块。 在这两种情况下,调用线程都必须拥有调用该方法的监视器上的locking。
从notify
文档( wait
和notifyAll
有类似的文档,但参考notify
的最完整的描述):
这个方法只能由这个对象监视器的所有者的线程调用。 线程以三种方式之一成为对象监视器的所有者:
- 通过执行该对象的同步实例方法。
- 通过执行同步对象的同步语句的主体。
- 对于types为Class的对象,通过执行该类的同步静态方法。
一次只有一个线程可以拥有一个对象的监视器。
在notifyAll
之后,只有一个线程能够实际退出 wait
,因为它们都必须再次获取相同的监视器 – 但是所有的线程都会被通知,所以一旦第一个notifyAll
退出同步块,下一个将获得锁等