java.lang.IllegalMonitorStateException wait and notify
java.lang.IllegalMonitorStateException wait and notify
我正在尝试使用wait和notify来暂停线程,直到调用某个特定的方法。我目前的设置如下:
一个线程有一个方法:
public void toggleTurnOver(){ if(turnOver == false){ turnOver = true; synchronized(this){ for(Player p: playerList){ p.notify(); } } }else{ turnOver = false; } }
这个方法将唤醒在该线程中等待的另一个wait:
synchronized(myGame){ if(!myGame.getTurnOver()){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } pr.println(myGame.getTurnOver()); pr.flush(); } }
它们都在相同的对象上同步,所以我不确定是什么原因导致抛出该异常。有什么想法吗?
抛出的确切错误是:
Exception in thread "Thread-3" Exception in thread "Thread-2" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:503) at Player.run(Player.java:112) java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at Game.toggleTurnOver(Game.java:764) at Game.run(Game.java:386)
java.lang.IllegalMonitorStateException是一个运行时异常,表示线程在对象的监视器上等待或通知时出现了非法的操作。这个异常通常在使用wait()和notify()方法时发生。
出现这个异常的原因是,在调用wait()方法和notify()方法时,线程必须先获得对象的监视器锁。如果线程没有获得锁或者不是锁的拥有者,就会抛出IllegalMonitorStateException异常。
解决这个问题的方法是,确保在调用wait()和notify()方法之前,线程已经获得了对象的监视器锁。这可以通过在同步块或同步方法中调用wait()和notify()方法来实现。同步块或同步方法会自动获得对象的监视器锁,保证线程在调用wait()和notify()方法时不会抛出IllegalMonitorStateException异常。
例如,在上述代码中,出现异常的原因是在调用notify()方法时,线程没有获得Player对象的监视器锁。解决这个问题的方法是,在调用notify()方法之前,先在同步块或同步方法中获取Player对象的监视器锁,然后再调用notify()方法。
以下是修改后的代码示例:
synchronized (Player.class) { Player.class.notify(); }
这样,线程就会在调用notify()方法时获得Player对象的监视器锁,不会抛出IllegalMonitorStateException异常。
总结起来,当使用wait()和notify()方法时,一定要确保线程已经获得了对象的监视器锁,否则会抛出java.lang.IllegalMonitorStateException异常。通过在同步块或同步方法中调用wait()和notify()方法,可以保证线程在操作对象的监视器时不会出现非法操作的异常。
java.lang.IllegalMonitorStateException是一个异常,表示线程在没有持有指定监视器的情况下尝试等待对象的监视器或通知正在等待对象的监视器的其他线程。
当我们在一个对象上调用wait()方法或notify()方法时,必须先获取该对象的监视器。如果我们没有获取到监视器,就会抛出IllegalMonitorStateException异常。
在上述代码中,我们可以看到在通知其他线程等待对象监视器时,使用了p.notify(),但没有对p进行同步。解决方法是在通知之前使用synchronized关键字对p进行同步,如下所示:
for(Player p: playerList) { synchronized(p){ p.notify(); } }
同样的,在等待对象监视器时,使用了this.wait()来等待监视器,但没有对this进行同步。解决方法是在等待之前使用synchronized关键字对this进行同步,如下所示:
if(!myGame.getTurnOver()){ try { synchronized(this){ wait(); } } catch (InterruptedException e) { // ... } }
需要注意的是,根据文档中的描述,这是唯一的句子,除了继承的构造函数。