Java等待并通知:IllegalMonitorStateException

我不完全了解waitnotifyObject )的工作,结果我不得不削减我的尝试到下面的代码段。

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对象,通过执行该类的同步静态方法。

您正在调用waitnotifyAll而不使用synchronized块。 在这两种情况下,调用线程都必须拥有调用该方法的监视器上的locking。

notify文档( waitnotifyAll有类似的文档,但参考notify的最完整的描述):

这个方法只能由这个对象监视器的所有者的线程调用。 线程以三种方式之一成为对象监视器的所有者:

  • 通过执行该对象的同步实例方法。
  • 通过执行同步对象的同步语句的主体。
  • 对于types为Class的对象,通过执行该类的同步静态方法。

一次只有一个线程可以拥有一个对象的监视器。

notifyAll之后,只有一个线程能够实际退出 wait ,因为它们都必须再次获取相同的监视器 – 但是所有的线程都会被通知,所以一旦第一个notifyAll退出同步块,下一个将获得锁等