问题描述
我已经创建了这个程序:
public class NotifyTest {
public synchronized void sendNotify() {
notifyAll();
}
public synchronized void receiveNotifies(int notifies) {
while (notifies > 0) {
try {
wait();
} catch (InterruptedException e) {}
notifies--;
System.out.println(Thread.currentThread().getName() + " left wait(),decremented notifies,current notifies count " + notifies);
}
}
public static void main(String[] args) {
NotifyTest notifyTest = new Notifytest();
for (int i = 0; i < 9; i++) {
Thread t1 = new Thread(() -> {
notifyTest.receiveNotifies(4);
});
t1.setName("receiveNotifiesThread: " + i);
t1.start();
}
System.out.println("Waiting until all receivers are started. Every Thread should be stopped after 4 notifies");
try {
Thread.sleep(1000);
} catch (Exception e) {}
new Thread(() -> {
for (int i = 0; i < 4; i++) {
System.out.println("Sent notify " + i);
notifyTest.sendNotify();
try {
Thread.sleep((int) Math.random());
} catch (Exception e) {}
}
}).start();
}
}
通常应在4次sendNotify()
调用之后停止所有线程。无论如何,当我运行该程序时,有时会挂起,因为receiveNotify()
线程错过了接收通知的时间。程序挂起时,输出如下所示:
> Waiting until all receivers are started. Every Thread should be stopped after 4 notifies
> Sent notify 0
> receiveNotifiesThread: 8 left wait(),current notifies count 3
> receiveNotifiesThread: 7 left wait(),current notifies count 3
> receiveNotifiesThread: 6 left wait(),current notifies count 3
> receiveNotifiesThread: 5 left wait(),current notifies count 3
> receiveNotifiesThread: 4 left wait(),current notifies count 3
> receiveNotifiesThread: 3 left wait(),current notifies count 3
> Sent notify 1
> receiveNotifiesThread: 2 left wait(),current notifies count 3
> receiveNotifiesThread: 1 left wait(),current notifies count 3
> receiveNotifiesThread: 0 left wait(),current notifies count 3
> Sent notify 2
> Sent notify 3
> receiveNotifiesThread: 0 left wait(),current notifies count 2
> receiveNotifiesThread: 1 left wait(),current notifies count 2
> receiveNotifiesThread: 2 left wait(),current notifies count 2
> receiveNotifiesThread: 3 left wait(),current notifies count 2
> receiveNotifiesThread: 4 left wait(),current notifies count 2
> receiveNotifiesThread: 5 left wait(),current notifies count 2
> receiveNotifiesThread: 6 left wait(),current notifies count 2
> receiveNotifiesThread: 7 left wait(),current notifies count 2
> receiveNotifiesThread: 8 left wait(),current notifies count 1
> receiveNotifiesThread: 7 left wait(),current notifies count 1
> receiveNotifiesThread: 6 left wait(),current notifies count 1
> receiveNotifiesThread: 5 left wait(),current notifies count 1
> receiveNotifiesThread: 4 left wait(),current notifies count 1
> receiveNotifiesThread: 3 left wait(),current notifies count 1
> receiveNotifiesThread: 2 left wait(),current notifies count 1
> receiveNotifiesThread: 1 left wait(),current notifies count 1
> receiveNotifiesThread: 0 left wait(),current notifies count 1
您知道如何解决吗?
解决方法
发送通知时...
for (int i = 0; i < 4; i++) {
System.out.println("Sent notify " + i);
notifyTest.sendNotify();
try {
Thread.sleep((int) Math.random());
} catch (Exception e) {}
}
...让线程休眠(int) Math.random()
毫秒。函数Math.random()
返回一个介于double
和0.0
之间的1.0
。将其强制转换为int
即可得到0
。因此,让线程休眠0
毫秒。
等待线程醒来时将其打印到控制台,这需要时间。如果您的通知程序线程根本没有休眠(0
毫秒),并且在前一个通知之后立即发出通知,则等待程序线程无法到达wait
调用,因此通知已没有效果。
要解决此问题,只需避免在sleep
通话中使用零,例如:
try {
Thread.sleep((int) (Math.random() * 100 + 1));
} catch (Exception e) {}