我有几个线程做了一些工作,然后必须去睡觉/等待一段不确定的时间。后来他们都需要被唤醒并恢复工作。我可以通过在对象上调用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.notify();
替换为myMonitorObject.notifyAll();
,那将无效,因为恢复工作的第一个线程会将wasSignalled
标志设置为false
,并且所有其他线程将被困在while loop。
我做了一些改动,使我能够唤醒所有线程:
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类?为什么我不能在wait
类本身上拨打notify
和MyWaitNotify
?
像这样:
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();
}
}
}
这似乎有效,我不应该这样做吗?
答案 0 :(得分:1)
使用生成整数。当一个线程阻塞时,阻塞直到生成整数发生变化。在调用notifyAll
之前,递增生成整数。
答案 1 :(得分:0)
Phaser是一个很好的高级工具。
final Phaser phaser = new Phaser(1);
doNotify()
phaser.arrive(); // increase phase
doWait()
int phase = phaser.getPhase();
phaser.awaitAdvance( phase ); // await phase change
私有对象上的 synchronized
具有其他任何人都无法对其进行synchronized
的优势。如果您执行synchronized(this)
,则其他人可能也希望将this
用作锁定对象。