[英]Understanding wait() and notify() methods
I'm trying to understand how Java's wait
and notify
methods work. 我试图了解Java的
wait
和notify
方法如何工作。 As per the documentation, wait()
causes thread to wait for subsequent calls to notify()
or notifyAll()
methods but for some reason notify
doesn't interrupt "waiting": 根据文档,
wait()
导致线程等待后续对notify()
或notifyAll()
方法的调用,但由于某种原因, notify
不会中断“ waiting”:
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread1 is started, waiting for notify()");
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
System.out.println(e.getLocalizedMessage());
}
}
System.out.println("waiting is over");
}
});
thread1.start();
// unblock thread1 in 2 seconds
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (thread1) {
thread1.notify();
}
}
You need to notify
the object that is being wait
ed on, not the thread that is waiting. 您需要
notify
正在wait
的对象,而不是正在wait
的线程。
In your case the object wait
ed on is an instance of an anonymous inner class, which is problematic because you cannot easily obtain a reference to it in order to notify
it. 在您的情况下,
wait
对象是匿名内部类的实例,这是有问题的,因为您无法轻松地获取对该对象的引用以进行notify
。 You could solve this by extending Thread
directly: 您可以通过直接扩展
Thread
来解决此问题:
Thread thread1 = new Thread() {
@Override
public void run() {
System.out.println("thread1 is started, waiting for notify()");
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
System.out.println(e.getLocalizedMessage());
}
}
System.out.println("waiting is over");
}
};
Now the this
(in synchronized (this)
) refers to the thread itself, and the wait
is called on the thread object too. 现在
this
(在synchronized (this)
)引用线程本身,并且也在线程对象上调用wait
。 In this case your current call to notify
should be fine, since it notifies the same object (which happens in this case to be the thread that is waiting - but just to be clear, that need not be the case). 在这种情况下,您的当前呼叫
notify
应该罚款,因为它会通知同一个对象( 发生在这种情况下是在等待线程-但仅仅是明确的,那不一定是这种情况)。
It isn't considered good practice to use an object for synchronisation that may also be used elsewhere; 使用对象进行同步(在其他地方也可以使用)不是一种好习惯。 instances of Thread would be an example of this, and in fact the documentation specifically advises against it:
Thread实例将是一个例子,实际上文档特别建议不要这样做:
It is recommended that applications not use
wait
,notify
, ornotifyAll
onThread
instances.建议应用程序不要在
Thread
实例上使用wait
,notify
或notifyAll
。
Also, you should correctly handle spurious wakeup ; 另外,您应该正确处理虚假唤醒 。 that is,
wait
may return because notify
/ notifyAll
was called elsewhere or perhaps was not even called at all. 也就是说,
wait
可能会返回,因为notify
/ notifyAll
在其他地方被调用了,或者甚至根本没有被调用。 As the documentation also says : 正如文档还说的那样 :
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup.
线程也可以唤醒,而不会被通知,中断或超时,即所谓的虚假唤醒。 While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied.
尽管在实践中这种情况很少发生,但是应用程序必须通过测试应该导致线程唤醒的条件来防范它,并在条件不满足时继续等待。 In other words, waits should always occur in loops [...]
换句话说,等待应该总是在循环中发生[...]
Therefore, your example should really use a separate variable to track whether the wakeup was intentional (due to an explicit notify
) or not. 因此,您的示例实际上应该使用一个单独的变量来跟踪唤醒是否是有意的(由于明确的
notify
)。
for some reason notify doesn't interrupt "waiting":
由于某些原因,notify不会中断“等待”:
@davmac's answer is correct but for posterity, there are some other ways you can do it because extending Thread
and calling wait()
and notify()
on the Thread
object is not recommended. @davmac的答案是正确的,但对于后代,您可以通过其他方法来实现,因为不建议扩展
Thread
并在Thread
对象上调用wait()
和notify()
。
The best way would be to create a lock object. 最好的方法是创建一个锁对象。 Making your lock objects
final
is always a good pattern although here it is also necessary to use it in the inner class. 尽管
final
在内部类中使用锁对象,将锁对象定为final
总是一个好的模式。
final Object lock = new Object();
Thread thread1 = new Thread(new Runnable() {
...
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
// always a good pattern
Thread.currentThread().interrupt();
System.out.println(e.getLocalizedMessage());
}
}
...
}
...
synchronized (lock) {
lock.notify();
}
// might as well wait for it to finish
thread1.join();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.