System.out.println("Thread state: " + threads[i].getState());
threads[i].notify();
产生以下输出:
Thread state: WAITING
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at MyPakc.An.run(An.java:49)
at java.lang.Thread.run(Thread.java:679)
发生了什么事?为什么我不能通知睡眠线程?
编辑:threads []类的代码:
package Part2;
import java.util.List;
import javax.swing.JPanel;
class BThread extends Thread{
private boolean completedThisIter = false;
@Override
public synchronized void run() {
while (true) {
completedThisIter = false;
doStuff()
System.out.println("Completed iter");
completedThisIter = true;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean getCompletedThisIter() {
return completedThisIter;
}
}
编辑:这是调用此
的代码public synchronized void run(){
// OTHER STUFF
for (int iter = 0; iter < 1212; ++iter){
System.out.println("Iter " + iter);
lastAssignedBallIndex = -1;
for (int i = 0; i < numThreads; i++) {
//System.out.println("Num " + numThreads + " " + i);
//ballThreads[i] = new BallThread(ballList.subList(lastAssignedBallIndex+1,lastAssignedBallIndex+numBallsPerThread),
// ballPanel);
//lastAssignedBallIndex += numBallsPerThread;
System.out.println("State " + ballThreads[i].getState());
if (ballThreads[i].getState() == Thread.State.NEW) {
ballThreads[i].start();
} else { //if (ballThreads[i].getState() == Thread.State.BLOCKED) {
System.out.println("Thread state: " + ballThreads[i].getState());
ballThreads[i].notify();
}
}
//try{
for (int i = 0; i < numThreads; i++) {
while (!ballThreads[i].getCompletedThisIter()) {
System.out.println("iter:" + iter + " ball:" + i + " " + ballThreads[i].getCompletedThisIter());
//wait(); // TODO elliminate polling here
}
}
System.out.println("Joined");
//}
// catch(InterruptedException ie){ie.printStackTrace();}
ballPanel.repaint();
notifyAll();
try{
Thread.sleep(2);
}
catch (InterruptedException ie){}
}
}
答案 0 :(得分:2)
您打印出ballThreads[i]
的状态,然后通知threads[i]
。不确定这是否是预期的行为,但是当您不拥有对象的监视器时,不允许您通知线程。您确定要在synchronized()
对象的threads[i]
块内调用此内容吗?
编辑:
是的,取消此代码的方法是同步的
在您编辑问题之后,synchronized
位于方法上,而不是对象的监视器,您需要将代码放在如下所示的块中:
synchronized(threads[i]) {
// some stuff
threads[i].notify();
}
此处的重要位(与方法声明中的synchronized
关键字相对)是您在对象上进行同步,然后在此块内,在对象<上调用notify()
/ em>的。例子:
public void run()
{
synchronized(myObject) {
// do some stuff
myObject.notify();
}
}
或
public void run()
{
synchronized(thread1) {
// do some stuff
thread1.notify();
}
}
或
public void run()
{
synchronized(syncObject) {
// do some stuff
syncObject.notify();
}
}
看模式?更多信息:http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
答案 1 :(得分:1)
wait()
和notifiy()
要求您在正在等待的对象上进行同步。如果您在用于锁定同步块的同一对象上执行wait()
和notify()
,那么您将摆脱非法监视器状态异常
答案 2 :(得分:1)
您完全误解了wait
/ notify
机制的工作方式。线程必须决定它需要等待的东西。然后线程必须调用wait
。那件事必须发生。然后你打电话给notify
告诉线程发生了什么事。
如果没有首先确定存在应该等待的特定内容,则无法调用线程wait
。而且,在发生线程需要通知的情况之前,您无法调用notify
。发生的事情应该与线程在决定等待时检查的内容相同。
您遇到错误的原因是与等待的事物相关联的同步根本不存在,这违反了wait
/ notify
的语义。
如果您正在等待邮箱非空,则应检查邮箱是否为空,如果是,请致电wait
。确保您仍在邮箱的同步例程中,否则您无法知道邮箱是否(仍然)为空。然后,当您在邮箱中放入一个字母(必须在邮箱的同步例程中)时,您调用notify
让任何等待的线程知道邮箱已更改状态。您必须等待线程可以测试的某些内容,例如邮箱的状态。