[英]java.lang.IllegalMonitorStateException whilst calling wait from synchronized block
Before I move onto using Condition variables I'm trying to understand object wait principles. 在继续使用Condition变量之前,我试图了解对象等待原理。 I wrote a little code to understand more but its not working as expected. 我写了一些代码以了解更多信息,但是它没有按预期工作。
What is supposed to happen is a Waiter class waits upon thread start. 应该发生的是Waiter类在线程启动时等待。 Meanwhile the Notifier class adds some elements to a list using a loop. 同时,Notifier类使用循环将一些元素添加到列表中。 Once the Notifier has done this it notifies the Waiter which should simply print that it has been notified but i get illegalmonitorstate exception 通知程序完成此操作后,它会通知服务员,该服务员应简单地打印已收到通知,但我收到了非法的monitorstate异常
This is my output 这是我的输出
Exception in thread "Waiter Thread" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at tutorials.waitnotify.Waiter.run(Waiter.java:26)
at java.lang.Thread.run(Thread.java:745)
0 [Waiter Thread] DEBUG tutorials.waitnotify.Waiter - Starting waiter....
2002 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter - Starting
notifier...
3005 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter - Element added [1]
4007 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter - Element added [2]
5012 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter - Element added [3]
Exception in thread "Notifier Thread" java.lang.IllegalMonitorStateException
7022 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter - Object about to
notify
at java.lang.Object.notify(Native Method)
at tutorials.waitnotify.Notifier.run(Notifier.java:42)
at java.lang.Thread.run(Thread.java:745)
This is the code As you can see I'm trying to synchronise on a common lock object. 这是代码如您所见,我正在尝试在通用锁定对象上进行同步。
public class Notifier implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(Waiter.class);
private List<Integer> list;
private Object commonLock;
public Notifier(Object lock) {
this.list = new ArrayList<>();
this.commonLock = lock;
}
public void run() {
LOGGER.debug("Starting notifier....");
synchronized (commonLock) {
for (int i = 1; i <= 3; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
LOGGER.debug("Interrupted");
}
list.add(i);
LOGGER.debug("Element added [{}]", i);
}
LOGGER.debug("About to notify");
notify();
}
}
}
public class Waiter implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(Waiter.class);
private final Object commonLock;
public Waiter(Object lock) {
this.commonLock = lock;
}
public void run() {
LOGGER.debug("Starting waiter....");
synchronized (commonLock) {
try {
wait(10000);
} catch (InterruptedException ie) {
LOGGER.debug("Interrupted");
}
}
LOGGER.debug("Object been notified");
}
}
public class WaiterNotifierMain {
public static void main(String[] args) {
BasicConfigurator.configure();
Object lock = new Object();
Waiter waiter = new Waiter(lock);
Notifier notifier = new Notifier(lock);
Thread waiterThread = new Thread(waiter);
Thread notifierThread = new Thread(notifier);
notifierThread.setName("Notifier Thread");
waiterThread.setName("Waiter Thread");
waiterThread.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifierThread.start();
}
}
Any pointers would be appreciated. 任何指针将不胜感激。 Thanks in advance 提前致谢
You should do 你应该做
You get an exception because you're waiting and notifying on "this". 因为您正在等待并通知“此”,所以您会得到一个例外。 And you didn't synchronize on "this". 而且您没有在“ this”上同步。
You might consider using notifyAll() instead of notify(): 您可以考虑使用notifyAll()而不是notify():
If you plan to have multiple Waiter threads, keep in mind that notify() will only wake up one Waiter thread at a time. 如果您打算有多个Waiter线程,请记住,notify()一次只会唤醒一个Waiter线程。 If you want to wake up ALL Waiter threads at once, you should use the notifyAll() method instead. 如果要立即唤醒所有Waiter线程,则应改用notifyAll()方法。
Even if know that you will never have more than one Waiter thread, I consider it best practice to use notifyAll() instead of notify(), since the Notifier object doesn't know how many threads are listening on the object... 即使知道您永远不会有一个以上的Waiter线程,但我认为最好的方法是使用notifyAll()而不是notify(),因为Notifier对象不知道有多少线程正在该对象上侦听...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.