Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java—等待方法未退出_Java_Multithreading_Concurrency - Fatal编程技术网

Java—等待方法未退出

Java—等待方法未退出,java,multithreading,concurrency,Java,Multithreading,Concurrency,我试图创建一个通用的MessagePrinter类,该类处理多个线程,每个线程每秒打印一条消息。此外,还有一个管理线程,它跟踪时间并每秒唤醒每个线程,在每个线程被唤醒后,每个线程都需要检查是否是打印消息的时间 然而,有一个主要的bug——当我在等待唤醒时调用wait()函数时,wait()函数并没有退出。我在谷歌上搜索过,但没有结果。下面是代码 import java.util.*; class MonitorCondition {} public class MessagePrinter

我试图创建一个通用的
MessagePrinter
类,该类处理多个线程,每个线程每秒打印一条消息。此外,还有一个管理线程,它跟踪时间并每秒唤醒每个线程,在每个线程被唤醒后,每个线程都需要检查是否是打印消息的时间

然而,有一个主要的bug——当我在等待唤醒时调用
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");
    }
}

代码挂起在这行:
试试{mc.wait();}
。也许这是我如何使用同步块的问题,但我在Java中看到了关于生产者-消费者的问题,这看起来正是根据答案应该如何实现的——但这并没有解决挂起的
wait()
函数问题。任何帮助都将不胜感激。

MessagePrinter的每个实例都有自己的字段mc副本,因此每个线程都在输入不同的监视器等待方法。调用notifyAll()没有任何作用,因为没有人会在监视器上等待。使mc为静态

编辑-即使你已经接受了答案,我想我会把它放在那里,因为你会遇到它。在管理器线程中调用.notifyAll()时,它将通知等待该对象监视器的所有线程,但在任何给定时间只有一个线程能够要求锁定。没有保证哪一方会获得锁,只有一方会在任何给定的时间获得锁。该线程将释放锁,然后如果条件为true,它将重置为false。同时,其他线程中的一个将被唤醒,并可能在信号标志重置为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!

wait()
做什么?您在同步什么?它是共享的吗?等等,我发现了另一个问题。7秒打印机仅捕获时间1、3、5、7。。。而5秒钟的打印机只能打印2、4、6、8。。。反之亦然(当5秒打印机“击败”7秒打印机时)进行打印。
使mc静止。
或创建一个
MonitorCondition
对象,通过让所有
Runnable
实例将其存储在实例字段中,与它们共享。好的,谢谢。但是,现在,
while(!signaled){
循环没有退出;
信号化的
应该设置为true。但是你回答了我的问题,因此接受了它。信号化的不同实例也是一样的。你需要能够通过引用每个客户端的信号化实例来找出如何向每个客户端发送信号,在这种情况下,可能只是使其为静态volatile,或使用Sotirios suggestion.OK,所以我会记得在Java中执行并发时始终将共享内容设置为静态。谢谢大家。@user2748947我编辑了它,并简要说明了您应该查看的逻辑。