我正在尝试创建一个通用的 MessagePrinter
类,该类处理多个线程,每个线程每秒打印一条消息。另外,还有一个管理器线程跟踪时间并每秒唤醒每个线程,每个线程被唤醒后,每个线程都需要检查是否到了打印消息的时间。
但是,有一个主要错误 - 当我在等待唤醒时调用 wait()
函数时,wait()
函数不会退出。我在谷歌上搜索过,但没有结果。下面是代码。
import java.util.*;
class MonitorCondition {}
public class MessagePrinter implements Runnable {
private static int time = 0;
private MonitorCondition mc = new MonitorCondition();
private int elapse;
private String title;
private boolean signaled;
public MessagePrinter(int elapse, String title) {
this.elapse = elapse;
this.title = title;
new Thread(this, title).start();
this.signaled = false;
}
// http://tutorials.jenkov.com/java-concurrency/thread-signaling.html
public void run() {
if(!title.equals("manager")) {
while(true) {
synchronized(mc) {
while(!signaled) {
try { mc.wait(); }
// Now check whether we can print.
catch(InterruptedException e) {;}
}
if(time % elapse == 0)
System.out.println(elapse + " second message!");
signaled = false;
}
}
} else {
while(true) {
try { Thread.sleep(1000); } // REGARDLESS of what elapse is set to
catch(InterruptedException e) {;}
synchronized(mc) {
System.out.println(++time);
signaled = true;
mc.notifyAll();
}
}
}
}
public static void main(String[] args) {
MessagePrinter m1 = new MessagePrinter(1, "manager");
MessagePrinter m2 = new MessagePrinter(7, "client1");
MessagePrinter m3 = new MessagePrinter(5, "client2");
}
}
代码卡在这一行:try { mc.wait(); }
。也许这是我如何使用同步块(synchronized block)的问题,但我在Java中看到了关于生产者-消费者的问题,这看起来正是根据答案应该如何实现的——但这并没有修复悬挂的 wait()
函数问题。任何帮助将不胜感激。
最佳答案
MessagePrinter 的每个实例都有自己的 mc 字段副本,因此每个线程都进入不同的监视器等待方法。调用notifyAll()不会执行任何操作,因为没有人会在managers mc监视器上等待。使 mc 静态。
编辑 - 尽管您已经接受了答案,但我想我会把它放在那里,因为您会遇到它。当您在管理器线程中调用 .notifyAll() 时,它将通知在该对象监视器上等待的所有线程,但在任何给定时间只有一个线程能够请求锁。无法保证哪一个会获得锁,只能保证在任何给定时间都会获得锁。该线程将释放锁,然后如果条件为真,它将重置信号为假。与此同时,其他线程之一将被唤醒,并且可能在有信号标志重置为 false 后不久评估您的 while 条件,这意味着您的一个或多个客户端可能无法打印其消息。
以下是运行一段时间后它如何在应用程序输出中体现的示例:
7 second message!
561
562
563
564
565
5 second message!
566
567
568
569
570
571
572
573
574
7 second message!
575
5 second message!
关于Java——等待方法未退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22978198/