【问题标题】:notifyAll() not awakening processesnotifyAll() 不唤醒进程
【发布时间】:2018-07-16 20:57:55
【问题描述】:

我正在编写一个小的 Java 程序,我需要在其中创建线程(我的代码中的哲学家),而这些哲学家需要在思考、饥饿和进食之间转换状态。 我对这个项目还没有那么远,我遇到了下一个问题:

public class NewMain {

    static Philosopher [] p;

    public static void main(String[] args) {
        p = new Philosopher[5];

        p[0] = new Philosopher(0);
        p[1] = new Philosopher(1);
        p[2] = new Philosopher(2);
        p[3] = new Philosopher(3);
        p[4] = new Philosopher(4);

        for (int i = 0; i<5; i++) {
            try{
                p[i].run();

                if(i == 4) {
                   p.notifyAll();
                }
            }
            catch(IllegalMonitorStateException e) {}   
        }  
    } 
}

我正在创建 5 个哲学家(线程)。每个人的代码中都有一个wait() 指令:

@Override
public void run() {
    int rand;

    if (status == 0) {
        System.out.println("Philosopher " + id + " is waiting.");
        try {
            wait();
            System.out.println("Awoken");
            while(status == 0) {
                    System.out.println("Philosopher " + id + " is thinking.");
                    sleep(100);
                    rand = ThreadLocalRandom.current().nextInt(0,100);                    
                    if(rand > 95){
                        status = 1;
                        System.out.println("Philosopher " + id + " changed state to hungry.");
                    }
                }
        }    
        catch(InterruptedException e) {
            System.out.println("Error!");
        }
        catch(IllegalMonitorStateException e) {}
    }
}

问题是当调用notifyAll()时,进程并没有被唤醒,它们在执行每个线程的run()方法后就死掉了。

如果有人想知道,我没有使用synchronized,因为我需要同时运行这些方法。

另外,我尝试将notifyAll() 放入线程的run() 方法中。

谁能告诉我发生了什么以及为什么线程没有继续 用他们的代码?

【问题讨论】:

  • 如果您想将run() 附加到实际的操作系统线程中,您必须调用Thread.start() 而不是Thread.run()
  • 你为什么要调用run来启动一个线程? Run 将像方法一样执行,它不会启动您的线程。这里需要notifyAll是什么?

标签: java multithreading wait notify dining-philosopher


【解决方案1】:

问题

  1. notify[All]()wait() 应该在同一个实例上使用。您在数组Philosopher[] p 上通知,但在等待this,这是一个Philosopher。这就像 在等 ,但 正在通知 Sarah 你会迟到的。

  2. 已创建线程,但尚未正确启动它们。调用run 将在当前线程中执行该方法。请改用start 方法。它同时开始执行。

  3. 要使用x.notify[All]()x.wait(),您必须在同步块synchronized(x) { ... } 内。忽略IllegalMonitorStateException 对您毫无帮助。

答案

...为什么线程不继续他们的代码?

他们可能会在第 4 个线程通知他们之后调用wait

...进程不会唤醒,它们只是死掉...

它们不会死,它们仍然会等待直到您终止程序。

我没有使用synchronized因为我需要同时运行这些方法

您需要正确同时运行这些方法,对吗?在这里,至少需要同步才能建立wait-notify 通信。

【讨论】:

    【解决方案2】:

    p 是一个 Runnable 数组。当你写

    p[i].run();
    

    然后,您正在使用存储在p[i] 位置的对象调用run 方法(实际上您还没有在这里启动一个线程,而是调用run 方法)。现在,根据notifyAll

    唤醒所有线程此对象的监视器等待。线程通过调用其中一个等待方法在对象的监视器上等待。

    1. 您应该使用start() 而不是run() 来启动新线程。
    2. notify()notifyAll 在线程等待获取当前对象上的监视器时使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多