Java 调用wait()时发生IllegalMonitorStateException

Java 调用wait()时发生IllegalMonitorStateException,java,multithreading,wait,Java,Multithreading,Wait,我的程序使用java中的多线程。 我已经成功运行了线程,但是当我使用thread.wait()时,它抛出了java.lang.IllegalMonitorStateException。 如何使线程等待直到收到通知?您需要处于同步的块中,才能使对象.wait()工作 此外,我建议查看并发程序包,而不是老式的线程程序包。它们更安全,也更安全 快乐编码 编辑 我假设您的意思是Object.wait(),因为您的例外情况是,当您尝试在不持有objects锁的情况下获得访问权限时会发生什么 您需要处于同步

我的程序使用java中的多线程。 我已经成功运行了线程,但是当我使用
thread.wait()
时,它抛出了
java.lang.IllegalMonitorStateException

如何使线程等待直到收到通知?

您需要处于
同步的
块中,才能使
对象.wait()
工作

此外,我建议查看并发程序包,而不是老式的线程程序包。它们更安全,也更安全

快乐编码

编辑


我假设您的意思是
Object.wait()
,因为您的例外情况是,当您尝试在不持有objects锁的情况下获得访问权限时会发生什么

您需要处于
同步的
块中,才能使
Object.wait()
工作

此外,我建议查看并发程序包,而不是老式的线程程序包。它们更安全,也更安全

快乐编码

编辑


我假设您的意思是
Object.wait()
,因为您的例外情况是,当您尝试在不持有objects锁的情况下获得访问权限时会发生什么

既然你没有发布代码,我们就在暗中工作。例外情况的细节是什么

您是从线程内部调用Thread.wait(),还是从线程外部调用

我这样问是因为根据javadoc for IllegalMonitorStateException,它是:

抛出以指示线程试图在对象的监视器上等待,或通知在不拥有指定监视器的情况下在对象监视器上等待的其他线程。 为了澄清此答案,此线程等待调用也会引发IllegalMonitorStateException,尽管它是从同步块中调用的:


     private static final class Lock { }
     private final Object lock = new Lock();

    @Test
    public void testRun() {
        ThreadWorker worker = new ThreadWorker();
        System.out.println ("Starting worker");
        worker.start();
        System.out.println ("Worker started - telling it to wait");
        try {
            synchronized (lock) {
                worker.wait();
            }
        } catch (InterruptedException e1) {
            String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
            System.out.println (msg);
            e1.printStackTrace();
            System.out.flush();
        }
        System.out.println ("Worker done waiting, we're now waiting for it by joining");
        try {
            worker.join();
        } catch (InterruptedException ex) { }

    }

因为你还没有发布代码,我们在暗中工作。例外情况的细节是什么

您是从线程内部调用Thread.wait(),还是从线程外部调用

我这样问是因为根据javadoc for IllegalMonitorStateException,它是:

抛出以指示线程试图在对象的监视器上等待,或通知在不拥有指定监视器的情况下在对象监视器上等待的其他线程。 为了澄清此答案,此线程等待调用也会引发IllegalMonitorStateException,尽管它是从同步块中调用的:


     private static final class Lock { }
     private final Object lock = new Lock();

    @Test
    public void testRun() {
        ThreadWorker worker = new ThreadWorker();
        System.out.println ("Starting worker");
        worker.start();
        System.out.println ("Worker started - telling it to wait");
        try {
            synchronized (lock) {
                worker.wait();
            }
        } catch (InterruptedException e1) {
            String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
            System.out.println (msg);
            e1.printStackTrace();
            System.out.flush();
        }
        System.out.println ("Worker done waiting, we're now waiting for it by joining");
        try {
            worker.join();
        } catch (InterruptedException ex) { }

    }

等待
对象
中定义,而不是在
线程
中定义。
线程上的监视器有点不可预测

尽管所有Java对象都有监视器,但通常最好有一个专用锁:

private final Object lock = new Object();
通过使用命名类,您可以以较小的内存开销(每个进程约2K)轻松读取诊断:

private static final class Lock { }
private final Object lock = new Lock();
为了
wait
notify
/
notifyAll
对象,需要使用
synchronized
语句持有锁。此外,您还需要一个
while
循环来检查唤醒条件(找到一篇关于线程的好文章来解释原因)

通知:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}

进入多线程时,了解Java语言和
Java.util.concurrent.locks
locks(和
Java.util.concurrent.atomic
)是非常值得的。但是尽可能使用
java.util.concurrent
数据结构。

wait
是在
对象中定义的,而不是在
线程中定义的。
线程上的监视器有点不可预测

尽管所有Java对象都有监视器,但通常最好有一个专用锁:

private final Object lock = new Object();
通过使用命名类,您可以以较小的内存开销(每个进程约2K)轻松读取诊断:

private static final class Lock { }
private final Object lock = new Lock();
为了
wait
notify
/
notifyAll
对象,需要使用
synchronized
语句持有锁。此外,您还需要一个
while
循环来检查唤醒条件(找到一篇关于线程的好文章来解释原因)

通知:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}
进入多线程时,了解Java语言和
Java.util.concurrent.locks
locks(和
Java.util.concurrent.atomic
)是非常值得的。但尽可能使用
java.util.concurrent
数据结构。

Thread.wait()调用在Thread.class对象上同步的代码中是有意义的。我认为这不是你的意思。
你问

如何使线程等待通知

您只能使当前线程等待。如果其他线程同意,则只能温和地要求其等待。
如果您想等待某个条件,您需要一个锁对象-Thread.class对象是一个非常糟糕的选择-它是一个单例AFAIK,因此在它上同步(线程静态方法除外)是危险的。
Tom Hawtin已经解释了同步和等待的细节。
java.lang.IllegalMonitorStateException
表示您试图等待未同步的对象-这样做是非法的。

Thread.wait()调用在Thread.class对象上同步的代码中有意义。我认为这不是你的意思。
你问

如何使线程等待通知

您只能使当前线程等待。如果其他线程同意,则只能温和地要求其等待。
如果您想等待某个条件,您需要一个锁对象-Thread.class对象是一个非常糟糕的选择-它是一个单例AFAIK,因此在它上同步(线程静态方法除外)是危险的。
Tom Hawtin已经解释了同步和等待的细节。
java.lang.IllegalMonitorStateException
表示您试图等待未同步的对象-这样做是非法的。

根据您的评论,听起来您正在做类似的事情:

Thread thread = new Thread(new Runnable(){
    public void run() { // do stuff }});

thread.start();
...
thread.wait();
有三个问题

  • 如同其他