【问题标题】:Wait And Notify IllegalMonitorStateException Anonymous Class等待并通知 IllegalMonitorStateException 匿名类
【发布时间】:2016-03-20 08:28:40
【问题描述】:

根据How to use wait and notify in Java?,我必须在同一个对象上同步才能调用notify。

我在同一个 haveCoffee 对象上进行了同步。为什么我在调用 notify 方法时收到 IllegalMonitorStateException ?

I am Sleeping
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at com.example.concurrent.basic.WaitAndNotify$2.run(WaitAndNotify.java:42)

在以下代码中:

public class WaitAndNotify {

    public static void main(String[] args) {

        Thread haveCoffee = new Thread() {
            public void run() {
                synchronized (this) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.print("I am awake and ready to have coffee");
                }
            }
        };

        Thread me = new Thread() {
            public void run() {
                synchronized (haveCoffee) {
                    try {
                        System.out.print("I am Sleeping");
                        Thread.sleep(4000);
                        notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        haveCoffee.start();
        me.start();
    }
}

【问题讨论】:

  • 你应该打电话给haveCoffee.notify()而不是notify()

标签: java multithreading


【解决方案1】:

在第一个线程上,您在拥有监视器的对象上调用 wait(对象是 this haveCoffee)。

但是,在第二个线程上,您在 me 上调用 notify(),同时拥有 haveCoffee 的监视器。

这应该可行:

public class WaitAndNotify {

    public static void main(String[] args) {

        final Thread haveCoffee = new Thread() {
            public void run() {
                synchronized (this) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.print("I am awake and ready to have coffee");
                }
            }
        };

        Thread me = new Thread() {
            public void run() {
                synchronized (haveCoffee) {
                    try {
                        System.out.print("I am Sleeping");
                        Thread.sleep(4000);
                        haveCoffee.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        haveCoffee.start();
        me.start();
    }
}

【讨论】:

  • 感谢工作。 stackoverflow.com/questions/886722/… 还声明:为了能够调用 notify(),您需要在同一个对象上进行同步。这是正确的还是需要在您要调用的对象上进行同步等待?
  • “为了能够调用 notify(),您需要在同一个对象上同步”是正确的。你的第二个陈述是隐含的。在对象上调用 wait() 或 notify() 之前,您必须同步对象。
  • 在调用 wait/notify 之前,您应该始终在对象上进行同步。自然,如果您不在调用 notify() 的同一对象上等待,您将不会获得所需的行为(不会通知等待代码)。
  • 有一个不同的语句1:您需要在同一个对象上同步(可以是任何对象)语句2:在您要调用wait on的对象上同步。
  • 如果你必须在一个对象上调用wait(),它应该是同步的。通常 wait() 或 notify() 调用只是大图的一小部分,同步保护大图的关键部分。
【解决方案2】:

来自 oracle 文档page

public class IllegalMonitorStateException
extends RuntimeException

抛出以表明一个线程试图在一个对象的监视器上等待,或者通知其他线程在一个对象的监视器上等待而不拥有指定的监视器。

每当您遇到此异常时,只需检查您的代码并检查wait()notify() 调用以及object on which these calls have been invoked。您可以轻松找出问题所在。

编辑:

wait()notify() 调用必须在对象上调用后,一旦你得到该对象的监视器。

【讨论】:

    【解决方案3】:

    你应该打电话来

    haveCoffee.notify()

    而不仅仅是

    通知()。

    如果您只调用notify(),它会调用this 对象上的notify() 方法,这是第二个线程me,因为您已在haveCoffee 线程上同步,这就是您出现异常的原因看到。

    所以 thread2 me 中的代码应该是这样的:

    synchronized (haveCoffee) {
        try {
            System.out.print("I am Sleeping");
            Thread.sleep(4000);
            haveCoffee.notify();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    

    【讨论】:

    • @ShivamSinha 这是真的,我相信您打算在haveCoffee 上致电notify() 而不仅仅是notify()。原因请参阅我的更新答案。
    猜你喜欢
    • 2011-10-30
    • 1970-01-01
    • 2019-12-23
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    相关资源
    最近更新 更多