notifyAll()没有唤醒进程

时间:2018-02-06 17:51:14

标签: java multithreading wait notify dining-philosopher

我正在编写一个小程序,我需要创建线程(我的代码中的哲学家),这些哲学家需要改变思维,饥饿和饮食之间的状态。 我没有那么远的项目,我有下一个问题:

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()方法中。

任何人都可以告诉我发生了什么,为什么线程不会继续 他们的代码?

2 个答案:

答案 0 :(得分:4)

问题

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

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

  3. 要使用x.notify[All]()x.wait(),您必须位于同步块synchronized(x) { ... }内。忽略IllegalMonitorStateException根本无济于事。

  4. 答案

      

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

    在第4个帖子通知后,他们可能会致电wait

      

    ......过程没有醒来,他们只是死了......

    他们不会死,他们还会等待,直到您终止该计划。

      

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

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

答案 1 :(得分:1)

p是一个Runnable数组。当你写作

p[i].run();

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

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

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