Java——等待方法未退出

标签 java multithreading concurrency

我正在尝试创建一个通用的 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/

相关文章:

java - 从 URL 检索 JSON 时,Android Bad Request IOException

c# - Python .NET、多线程和 Windows 事件循环

c# - 如果当前失败,如何继续队列中的其他任务?

java - 这个 java .execute() 方法调用是什么意思?

ios - 如何将 "tell"管理它必须删除和/或插入的对象的父上下文?

java - 通过超链接预填充 iPhone 日历事件

java - java I/O 的字符串数组逻辑问题

java - Android - ServerSocket 权限被拒绝

java - 这是使用 ThreadPoolExecutor 的正确方法吗?

concurrency - 请澄清VHDL中顺序和并发执行的概念