【发布时间】:2016-01-30 23:49:34
【问题描述】:
我有几个线程在做一些工作,然后必须进入睡眠/等待一个不确定的时间。稍后,他们都需要被唤醒并继续工作。我可以通过在一个对象上调用wait(),然后在需要恢复时在同一个对象上调用notifyall() 来做到这一点。在研究这个问题时,我发现了这个教程:http://tutorials.jenkov.com/java-concurrency/thread-signaling.html
显然,通过将信号存储在信号类中并在 while 循环中检查信号成员变量来防止丢失信号和虚假唤醒是一种很好的做法。
这是教程中的代码示例:
public class MonitorObject{
}
public class MyWaitNotify3{
MonitorObject myMonitorObject = new MonitorObject();
boolean wasSignalled = false;
public void doWait(){
synchronized(myMonitorObject){
while(!wasSignalled){
try{
myMonitorObject.wait();
} catch(InterruptedException e){...}
}
//clear signal and continue running.
wasSignalled = false;
}
}
public void doNotify(){
synchronized(myMonitorObject){
wasSignalled = true;
myMonitorObject.notify();
}
}
}
此代码有效,但我需要唤醒所有线程,而不仅仅是一个。如果我用myMonitorObject.notifyAll(); 替换myMonitorObject.notify();,那将无法正常工作,因为第一个恢复工作的线程会将wasSignalled 标志设置为false,并且所有其他线程将被困在while 循环中。
我进行了一些更改,使我能够唤醒所有线程:
MonitorObject myMonitorObject = new MonitorObject();
boolean wasSignalled = false;
public void doWait(){
synchronized(myMonitorObject){
while(!wasSignalled){
try{
myMonitorObject.wait();
} catch(InterruptedException e){
}
}
}
}
public void resetSignal() {
wasSignalled = false;
}
public void doNotifyAll() {
synchronized(myMonitorObject){
wasSignalled = true;
myMonitorObject.notifyAll();
}
}
但这不是一个很好的解决方案,因为现在我不能只唤醒一个线程,我必须在doNotify之后重置信号,然后才能再次使用doWait。
有没有人可以让我在等待的线程上同时使用notify 或notifyAll 的解决方案?
关于示例的一件事我不明白,为什么我必须使用单独的 MonitorObject 类?为什么我不能在 MyWaitNotify 类本身上调用 wait 和 notify?
像这样:
public class WaitNotify {
boolean wasSignalled = false;
public void doWait(){
synchronized(this){
while(!wasSignalled){
try{
wait();
} catch(InterruptedException e){
}
}
}
}
public void resetSignal() {
wasSignalled = false;
}
public void doNotifyAll() {
synchronized(this){
wasSignalled = true;
notifyAll();
}
}
}
这似乎有效,有什么理由我不应该这样做?
【问题讨论】:
标签: java multithreading wait notify