Java - 等待方法没有退出

时间:2014-04-10 03:37:39

标签: java multithreading concurrency

我试图创建一个通用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()功能问题。任何帮助将不胜感激。

1 个答案:

答案 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!