【问题标题】:Why wait() is not working after notifyAll() is invoked为什么调用 notifyAll() 后 wait() 不起作用
【发布时间】:2015-04-15 14:06:14
【问题描述】:

我不知道该怎么办!我是初学者, public void checkUp(){} 工作正常,但内部方法notifyAll() 不会通知wait()

public class Doctor extends Thread {
    public static void main(String[] args) {
        Doctor doctor = new Doctor();
        Patient patient1 = new Patient(doctor);
        Patient patient2 = new Patient(doctor);
        patient1.setName("Patient One");
        patient2.setName("Patient Two");
        patient1.start();
        patient2.start();
   }
}

//这是患者类

class Patient extends Thread {
    Doctor d;
    static boolean isAlready = false;

    public Patient(Doctor d) {
        this.d = d;
    }

    public void run() {
        synchronized(this) {
            if (isAlready == false) {
                isAlready = true;
                try {
                    System.out.println(Thread.currentThread().getName() + " Wait to see Doctor\n");
                    wait();
                    checkup();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            checkup();
        }

    }

    public void checkup() {
        synchronized(this) {
            try {
                System.out.println(Thread.currentThread().getName() + " Enter Doctor's Room!\n");
                System.out.println("After Consulting Doctor! '" + Thread.currentThread().getName() + "' Paid fees to Doctor\n");
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + " Notify to next Patient to enter Doctor's Room!\n");
                notifyAll();
                System.out.println(Thread.currentThread().getName() + " Leaves Hospital\n");

            } catch (Exception e) {

            }

            isAlready = false;
        }

    }
}

【问题讨论】:

  • 您好,欢迎您,您应该尽量提供尽可能多的信息
  • 什么时候调用checkup方法(run方法除外)?
  • 您的所有患者都等到另一个患者调用“notifyAll”...所以没有患者调用 notifyAll,永远不会(因为所有患者都在等待)...XD
  • 如果你想同步很多Patients,你需要使用共享对象而不是this。现在,notifyAll() 仅通知在监视器上等待特定Patient 对象的线程,而不是所有线程。

标签: java multithreading tags wait notify


【解决方案1】:

我相信您正在尝试跨不同线程(患者)共享公共资源(医生),在这种情况下,您需要锁定医生而非患者的公共对象。

试试这个。

class Patient extends Thread {
    Doctor d;
    public Patient(Doctor d) {
        this.d = d;
    }
    public void run() {
        synchronized (d) {
            checkup();
        }
    }
    public void checkup() {
        System.out.println(Thread.currentThread().getName()
                + " Enter Doctor's Room!\n");
        System.out.println("After Consulting Doctor! '"
                + Thread.currentThread().getName() + "' Paid fees to Doctor\n");
        Thread.sleep(1000);
        System.out.println(Thread.currentThread().getName()
                + " Notify to next Patient to enter Doctor's Room!\n");
        System.out.println(Thread.currentThread().getName()
                + " Leaves Hospital\n");
    }
}

【讨论】:

  • 感谢 pradeep!但我只是了解等待和通知!所以只有我写了一个程序!但它不会正常工作
  • 您的代码有问题,有两个线程,每个线程都在调用自己的等待(this),在对某个对象调用等待后,其他线程需要在同一对象上调用 notify/notifyAll 以唤醒等待线程.
【解决方案2】:

您有两个 Patient 对象,每个对象只有 wait()s 或 notifyAll()s 本身。如果 Patient 对象进入 wait() 调用,谁会通知它?


您正在尝试为队列建模:有一位医生,并且有很多患者必须轮流等候看医生。

通过将线程与每个患者相关联,并阻塞每个患者线程直到轮到它,您正在利用操作系统用来实现线程同步的隐藏队列。

为什么不使用显式队列呢?为什么不通过队列中的对象来表示患者,并通过一个线程从队列中一个接一个地挑选患者对象并为他们提供服务来为医生建模?

【讨论】:

    【解决方案3】:
    public class Patient extends Thread{
    Doctor d;
        static boolean isAlready = false;
    
        public Patient(Doctor d) {
            this.d = d;
        }
    
        public static void main(String[] args) {
            Doctor doctor = new Doctor();
            doctor.start();
    }   
        public void run() {
            synchronized (d) {
            //  System.out.println(Thread.currentThread().getName()+" Runn\n");
                if (isAlready == false) {
                    try {
                        System.out.println(Thread.currentThread().getName()+ " Wait to see Doctor\n\n");
                        isAlready = true;
                        d.wait();
                        Thread.sleep(2000);
                        checkup();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
    
                }else{
                    checkup();
                }
            }
    
        }
        public  void checkup() {
            synchronized (d) {
                try {
                    System.out.println(Thread.currentThread().getName()+ " Enter Doctor's Room!\n");
                    System.out.println("After Consulting Doctor! '"+ Thread.currentThread().getName()+ "' Paid fees to Doctor\n");
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName()+ " Notify to next Patient to enter Doctor's Room!\n");
                    d.notify();
                    isAlready = false;
                    System.out.println(Thread.currentThread().getName()+ " Leaves Hospital\n");
    
                } catch (Exception e) {
    
                }
    
                }
        }
    
    }
    
    
    class Doctor extends Thread {
        public void run(){
    
            String patientName[] ={"Aravi","Elaa","Sethu","Bala","Ram","Sharukazen","Sathish","Gold"};
            Patient[] patients=new Patient[patientName.length];
            Doctor doctor = new Doctor();
            for (int i =0; i<patientName.length;i++){
            patients[i] = new Patient(doctor);
            patients[i].setName(patientName[i]);
            patients[i].start();
            }
    
    }
    

    }

    我终于找到了答案。谢谢你们!

    【讨论】:

      【解决方案4】:

      两个线程都会调用wait() 并在调用checkup() 之前永远在那里等待。由于两个线程都在等待,因此它们都不能继续checkup()并从其中调用notifyAll()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-11
        • 2017-08-21
        • 2012-07-08
        • 1970-01-01
        • 2013-12-18
        • 1970-01-01
        • 2016-01-12
        • 1970-01-01
        相关资源
        最近更新 更多