我试图创建一个通用MessagePrinter
类来处理多个线程,每个线程每隔一秒打印一条消息。此外,还有一个管理器线程可以跟踪时间并每秒唤醒每个线程,每个线程被唤醒后,每个线程都需要检查是否有时间打印消息。
但是,有一个主要错误 - 当我等待唤醒时调用wait()
函数时,wait()
函数不会退出。我在Google上搜索过,但无济于事。以下是代码。
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块的问题,但我在Java中看到了关于生产者 - 消费者的问题,而这看起来应该如何根据答案实施 - 但是这还没有解决悬挂wait()
功能问题。任何帮助将不胜感激。
答案 0 :(得分:1)
MessagePrinter的每个实例都有自己的字段mc副本,因此每个线程都在输入不同的monitor wait方法。调用notifyAll()什么也不做,因为没有人会在管理器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!