Java - 何时使用notify或notifyAll?

时间:2010-05-14 13:09:32

标签: java multithreading concurrency synchronization

为什么java.lang.Object有两种通知方式 - notifynotifyAll?似乎notifyAll至少做了notify所做的一切,为什么不一直只使用notifyAll?如果使用notifyAll代替notify,程序是否仍然正确,反之亦然?是什么影响了这两种方法之间的选择?

4 个答案:

答案 0 :(得分:2)

  //contribute By E.Thulasiram and Team
   class AA extends Thread{
AA a;
public void get(AA a){
    this.a=a;
}
public void run(){
    System.out.println("one");
    synchronized (a) {
        try{
            a.wait();
            System.out.println("one wake up");
            this.wait();
        }catch(Exception e){
            System.out.println(e);
        }
    }
}
     }
     class BB extends Thread{
AA a;
public void get(AA a){
    this.a=a;
}
public void run(){
    System.out.println("two");
    synchronized (a) {
        try{
            a.wait();
            System.out.println("two wake up");
        }catch(Exception e){
            System.out.println(e);
        }
    }
 }
     }
     class CC extends Thread{
AA a;
public void get(AA a){
    this.a=a;
}
public void run(){
    synchronized (a) {
        a.notifyAll();
        System.out.println("NotifyAll");
    }
}
    } 
    class DD{
public static void main(String args[]){
    AA a=new AA();
    BB b=new BB();
    CC c=new CC();
    a.get(a);
    a.start();
    b.get(a);
    b.start();
    c.get(a);
    c.start();
}
    }

答案 1 :(得分:1)

根据notify的JavaDoc:

  

唤醒正在此对象监视器上等待的单个线程。如果任何线程正在等待此对象,则选择其中一个线程被唤醒。选择是任意的,由实施决定。线程通过调用其中一个等待方法等待对象的监视器。

如果您的应用程序使用(例如)队列放置项目,然后有许多工作线程将项目从队列中拉出来,那么这可能很有用。当项目准备就绪时,您可以调用notify唤醒单个工作人员来处理该项目。不可否认,这个例子有点人为 - 有可能更好的方法在Java中实现它 - 但你明白了。

答案 2 :(得分:1)

两个典型的例子。

假设你有一个生产者线程和一个消费者线程。生产者生产的每个“包”应由消费者消费。消费者将某些东西放入队列然后调用notify()(只有一个消费者应该通过处理一个“数据包”。)

假设您希望在漫长的过程结束时收到通知。你想要一个哔哔声和一个屏幕更新。该进程执行notifyAll()以通知蜂鸣线程和屏幕更新线程。

答案 3 :(得分:-1)

不同之处在于notify()仅重击等待当前线程的一个线程。对于大多数生产者/消费者和委托和等待应用程序,这是正确的使用方法。此外,如果只有一个其他线程在当前线程上等待,则不需要通知多个等待线程。

相反,notifyAll()重击等待当前线程的其他线程的所有。这在每个(相关的)休眠线程必须执行某些操作的情况下更有用,例如响应通知线程所包含的致命或高重要性事件。