IllegalMonitorStateException在wait()调用
我在我的程序中使用java的multithreading。 我已经成功运行线程,但是当我使用Thread.wait()
,它抛出java.lang.IllegalMonitorStateException
。 我怎样才能使一个线程等待,直到它会被通知?
您需要位于synchronized
块中,以使Object.wait()
正常工作。
此外,我build议查看并发包,而不是老学校线程包。 他们更安全, 更容易处理 。
快乐的编码。
编辑
我假定你的意思是Object.wait()
因为你的exception是当你试图获得访问权限,而不保持对象locking时发生的。
wait
在Object
定义,而不是Thread
。 Thread
上的监视器有点不可预知。
虽然所有Java对象都有监视器,但通常最好有一个专用的锁:
private final Object lock = new Object();
通过使用一个命名的类,您可以以小的内存成本(每个进程大约2K)轻松地读取诊断信息:
private static final class Lock { } private final Object lock = new Lock();
为了wait
或notify
/ notify
一个对象,你需要用synchronized
语句来保持锁。 此外,您将需要一个while
循环来检查唤醒条件(在线程中find一个好的文本来解释原因)。
synchronized (lock) { while (!isWakeupNeeded()) { lock.wait(); } }
通知:
synchronized (lock) { makeWakeupNeeded(); lock.notifyAll(); }
进入multithreading时,理解Java语言和java.util.concurrent.locks
锁(和java.util.concurrent.atomic
)是非常值得的。 但是,只要可以,就使用java.util.concurrent
数据结构。
我知道这个线程已经差不多2年了,但是还是需要closures这个线程,因为我也是来这个Q / A会话的同一个问题。
请一次又一次地阅读illegalMonitorException的这个定义。
IllegalMonitorException被抛出,表示一个线程试图等待一个对象的监视器,或者通知没有拥有指定监视器的对象监视器上等待的其他线程。
这行一次又一次地说,IllegalMonitorException来的时候发生的两种情况之一….
1>等待对象的显示器,而不拥有指定的显示器。
2>通知等待对象监视器的其他线程,而不拥有指定的监视器。
有些人可能已经得到了他们的答案…谁都没有,那么请检查2陈述….
同步(对象)
的Object.wait()
如果两个对象都是相同的,那么不会出现illegalMonitorExceptionexception。
现在再次阅读IllegalMonitorException定义,你不会再把它忘记…
基于你的意见,听起来像你正在做这样的事情:
Thread thread = new Thread(new Runnable(){ public void run() { // do stuff }}); thread.start(); ... thread.wait();
有两个问题。 首先,正如其他人所说, obj.wait()
只能在当前线程持有obj
的原始互斥量时调用。 如果当前线程不包含互斥锁,则会看到您所看到的exception。
第二个(更重要的)问题是thread.wait()
不会做你期望的事情。 具体来说, thread.wait()
不会导致指定的线程等待。 相反,它会导致当前线程等待,直到其他线程调用thread.notify()
或thread.notifyAll()
。
实际上没有安全的方法来强制一个线程实例暂停,如果它不想。 (离Java最近的是不推荐使用的Thread.suspend()
方法,但是这个方法本质上是不安全的,就像Javadoc中所解释的那样)。
如果你想让新启动的线程暂停,最好的办法是创build一个CountdownLatch实例,然后让latch上的线程调用await()
来暂停。 主线程然后调用countDown()
上的countDown()
来让暂停的线程继续。
既然你没有发布代码,我们在黑暗中工作。 什么是例外的细节?
你是从线程内部还是外部调用Thread.wait()?
我问这是因为根据IllegalMonitorStateException的javadoc,它是:
抛出以指示线程试图等待对象的监视器或通知其他线程等待对象的监视器而不拥有指定的监视器。
为了澄清这个答案,这个在线程上等待的调用也会抛出IllegalMonitorStateException,尽pipe在同步块内被调用:
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()调用在与Thread.class对象同步的代码中有意义。 我不认为这是你的意思。
你问
我怎样才能使一个线程等待,直到它会被通知?
你只能使你当前的线程等待。 任何其他线程只能轻轻地等待,如果它同意。
如果你想等待一些条件,你需要一个锁对象 – Thread.class对象是一个非常不好的select – 它是一个单身AFAIK,所以它同步(除了线程静态方法)是危险的。
Tom Hawtin已经解释了同步和等待的细节。 java.lang.IllegalMonitorStateException
意味着你正在试图等待你没有同步的对象 – 这样做是非法的。
不知道这是否会帮助别人,但这是解决我的问题的关键部分用户“汤姆霍廷 – tacklin”的答案上面:
synchronized (lock) { makeWakeupNeeded(); lock.notifyAll(); }
只是“lock”作为synchronized()中的一个parameter passing的事实,它也用于“lock”.notifyAll();
一旦我在这两个地方做到了,我就能做到
(对于@Tom Hawtin回答的post)
你怎么能实例化锁?()
private static final class Lock { } private final Object lock = new Lock();//This is incorrect.
它是
private final Object lck = new ReentrantLock();
你怎么能实例化一个锁?它的一个接口.. !!!