我正在设计两个线程:一个必须获取播放器的名称,第二个线程必须等待设置的名称才能继续,但第一个线程中的notify()all抛出了IllegalMonitorStateException错误。
private NameFecth nameFetch;
private UseName useName;
private Object nameSetLock;
public static void method{
nameSetLock = new Object()
nameFetch = new NameFetch(nameSetLock);
useName = new UseName(nameSetLock);
Thread nameFetchThread = new Thread(nameFetch);
nameFetchThread.start();
Thread useNameThread = new Thread(useName);
useNameThread.start();
}
public class NameFetch implements Runnable{
/*variables and constructers*/
public void run(){
/*get name and set the variable somehow*/
synchronized(nameSetLock){
notifyAll();
}
}
}
public class UseName implements Runnable{
/*variables and constructers*/
public void run(){
while(!nameBeenSet){
synchronized(nameSetLock){
try{
wait();
}catch(InterruptedException e) {}
}
}
}
我做错了什么?
答案 0 :(得分:15)
您正在调用wait
和notify
,而不会同步您正在等待或通知的内容。如Object.notifyAll
中所述:
抛出:
IllegalMonitorStateException
- 如果当前线程不是此对象监视器的所有者。
所以这个:
synchronized(nameSetLock){
notifyAll();
}
应该是:
synchronized(nameSetLock){
nameSetLock.notifyAll();
}
...同样适用于wait
。请注意,您当前的代码甚至无法编译,因为您使用的是syncronized
而不是synchronized
,这表明您没有发布实际的代码。在键入代码时,您实际上已经更改了问题 - 在这种情况下,您应该编辑您的问题以使其更具代表性。
答案 1 :(得分:1)
看起来你的问题是你正在使用锁。您的同步块是在nameSetLock上,并且您正在NameFetch对象实例上调用您的notifyall(这是一个同步的(这个)。
你应该这样做 当您要使用lock和nameSetLock.notifyAll进行通知时,请设置nameSetLock.wait。
答案 2 :(得分:1)
来自IllegalStateException
Thrown to indicate that a thread has attempted to wait on an object's
monitor or to notify other threads waiting on an object's monitor
without owning the specified monitor.
您试图在没有该对象锁定的情况下调用wait()和notifyAll()。
请尝试@Jon建议它会起作用。
答案 3 :(得分:0)
当我忘记在方法调用中添加synchronized时,会发生这种情况。