fra*_*kee 2 java concurrency multithreading
我试图了解 Javawait和notify方法的工作原理。根据文档,wait()导致线程等待对notify()或notifyAll()方法的后续调用,但由于某种原因notify不会中断“等待”:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
您需要notify的是正在wait编辑的对象,而不是正在等待的线程。
在您的情况下,对象waited 是匿名内部类的实例,这是有问题的,因为您无法轻松获得对它的引用notify。您可以通过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");
}
};
Run Code Online (Sandbox Code Playgroud)
现在this(in synchronized (this)) 指的是线程本身,并且wait也在线程对象上调用了。在这种情况下,您当前的调用notify应该没问题,因为它通知同一个对象(在这种情况下发生的是正在等待的线程 - 但要清楚的是,情况不一定如此)。
将一个对象用于同步,但也可能在其他地方使用,这被认为不是一种好的做法;Thread 的实例就是一个例子,实际上文档特别建议不要这样做:
建议应用程序无法使用
wait,notify或notifyAll在Thread实例。
此外,您应该正确处理虚假唤醒;也就是说,wait可能会因为notify/notifyAll在别处被调用或者甚至根本没有被调用而返回。正如文档中所说:
线程也可以在没有被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这在实践中很少发生,但应用程序必须通过测试应该导致线程被唤醒的条件来防止它,如果条件不满足则继续等待。换句话说,等待应该总是发生在循环中 [...]
因此,您的示例应该真正使用一个单独的变量来跟踪唤醒是否是有意的(由于显式notify)。
| 归档时间: |
|
| 查看次数: |
399 次 |
| 最近记录: |