为了账号安全,请及时绑定邮箱和手机立即绑定

Java等待和通知:IllegalMonitorStateException

Java等待和通知:IllegalMonitorStateException

一只萌萌小番薯 2019-08-13 15:45:53
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!");   }}目前我在调用时遇到IllegalMonitorStateException Main.main.wait();,但我不明白为什么。从我所看到的,我需要同步Runner.run,但这样做我认为它只会通知一个线程,当想法是通知他们所有。我看过了java.util.concurrent,但我找不到合适的替代品(也许我只是遗漏了一些东西)。
查看完整描述

2 回答

?
守着星空守着你

TA贡献1799条经验 获得超8个赞

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()

Javadoc文档wait()提到这一点:

此方法只应由作为此对象监视器所有者的线程调用。有关notify线程可以成为监视器所有者的方式的说明,请参阅方法。

抛出:

IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。

来自notify()

线程以三种方式之一成为对象监视器的所有者:

  • 通过执行该对象的同步实例方法。

  • 通过执行synchronized在对象上同步的语句的主体。

  • 对于类型的对象Class,通过执行该类的同步静态方法。


查看完整回答
反对 回复 2019-08-13
?
三国纷争

TA贡献1804条经验 获得超7个赞

你打电话都waitnotifyAll不使用synchronized块。在这两种情况下,调用线程必须拥有您调用方法的监视器上的锁。

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

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

  • 通过执行该对象的同步实例方法。

  • 通过执行在对象上同步的synchronized语句的主体。

  • 对于Class类型的对象,通过执行该类的同步静态方法。

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

只有一个线程能够一次实际退出 waitnotifyAll因为他们都必须再次获得相同的监视器 - 但是所有线程都会被通知,所以只要第一个线程退出同步块,下一个将获得锁等


查看完整回答
反对 回复 2019-08-13
  • 2 回答
  • 0 关注
  • 393 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信