当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Java notify()和notifyAll()的区别用法及代码示例


具有wait()方法的notify()和notifyAll()方法用于线程之间的通信。通过调用wait()方法进入等待状态的线程将处于等待状态,直到其他线程在同一对象上调用notify()或notifyAll()方法为止。
现在的问题是,既使用notify()方法又使用notifyAll()方法向等待的线程发出通知,那么它们之间有什么区别,或者我们应该在哪里使用notify()方法,哪里应该使用notifyAll()方法?
让我们了解notify()方法的行为:

// Java program to illustrate the 
// behaviour of notify() method 
class Geek1 extends Thread { 
public void run() 
    { 
        synchronized(this) 
        { 
            System.out.println 
            (Thread.currentThread().getName() + "...starts"); 
            try { 
                this.wait(); 
            } 
            catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
            System.out.println 
            (Thread.currentThread().getName() + "...notified"); 
        } 
    } 
} class Geek2 extends Thread { 
    Geek1 geeks1; 
    Geek2(Geek1 geeks1) 
    { 
        this.geeks1 = geeks1; 
    } 
public void run() 
    { 
        synchronized(this.geeks1) 
        { 
            System.out.println 
            (Thread.currentThread().getName() + "...starts"); 
  
            try { 
                this.geeks1.wait(); 
            } 
            catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
            System.out.println 
            (Thread.currentThread().getName() + "...notified"); 
        } 
    } 
} class Geek3 extends Thread { 
    Geek1 geeks1; 
    Geek3(Geek1 geeks1) 
    { 
        this.geeks1 = geeks1; 
    } 
public void run() 
    { 
        synchronized(this.geeks1) 
        { 
            System.out.println 
            (Thread.currentThread().getName() + "...starts"); 
            this.geeks1.notify(); 
            System.out.println 
            (Thread.currentThread().getName() + "...notified"); 
        } 
    } 
} class MainClass { 
public static void main(String[] args) throws InterruptedException 
    { 
  
        Geek1 geeks1 = new Geek1(); 
        Geek2 geeks2 = new Geek2(geeks1); 
        Geek3 geeks3 = new Geek3(geeks1); 
        Thread t1 = new Thread(geeks1, "Thread-1"); 
        Thread t2 = new Thread(geeks2, "Thread-2"); 
        Thread t3 = new Thread(geeks3, "Thread-3"); 
        t1.start(); 
        t2.start(); 
        Thread.sleep(100); 
        t3.start(); 
    } 
}

输出:

Thread-1...start
Thread-2...starts
Thread-3...starts
Thread-3...notified
Thread-1...notified

让我们了解notifyAll()方法的行为:

// Java program to illustrate the 
// behavior of notifyAll() method 
class Geek1 extends Thread { 
public void run() 
    { 
        synchronized(this) 
        { 
            System.out.println 
            (Thread.currentThread().getName() + "...starts"); 
            try { 
                this.wait(); 
            } 
            catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
            System.out.println 
            (Thread.currentThread().getName() + "...notified"); 
        } 
    } 
} class Geek2 extends Thread { 
    Geek1 geeks1; 
    Geek2(Geek1 geeks1) 
    { 
        this.geeks1 = geeks1; 
    } 
public void run() 
    { 
        synchronized(this.geeks1) 
        { 
            System.out.println 
            (Thread.currentThread().getName() + "...starts"); 
  
            try { 
                this.geeks1.wait(); 
            } 
            catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
            System.out.println 
            (Thread.currentThread().getName() + "...notified"); 
        } 
    } 
} class Geek3 extends Thread { 
    Geek1 geeks1; 
    Geek3(Geek1 geeks1) 
    { 
        this.geeks1 = geeks1; 
    } 
public void run() 
    { 
        synchronized(this.geeks1) 
        { 
            System.out.println 
            (Thread.currentThread().getName() + "...starts"); 
  
            this.geeks1.notifyAll(); 
            System.out.println 
            (Thread.currentThread().getName() + "...notified"); 
        } 
    } 
} class MainClass { 
public static void main(String[] args) throws InterruptedException 
    { 
  
        Geek1 geeks1 = new Geek1(); 
        Geek2 geeks2 = new Geek2(geeks1); 
        Geek3 geeks3 = new Geek3(geeks1); 
        Thread t1 = new Thread(geeks1, "Thread-1"); 
        Thread t2 = new Thread(geeks2, "Thread-2"); 
        Thread t3 = new Thread(geeks3, "Thread-3"); 
        t1.start(); 
        t2.start(); 
        Thread.sleep(100); 
        t3.start(); 
    } 
}

输出:

Thread-1...starts
Thread-2...starts
Thread-3...starts
Thread-3...notified
Thread-2...notified
Thread-1...notified

Differences between notify() and notifyAll()



  1. 线程数通知:我们可以使用notify()方法仅向一个正在等待特定对象的线程发出通知,而借助notifyAll()方法,我们可以将通知给予特定对象的所有等待线程。
  2. 通过JVM通知线程:如果有多个线程在等待通知,而我们使用notify()方法,则只有一个线程得到通知,其余线程则必须等待进一步的通知。哪个线程将收到我们无法预期的通知,因为它完全取决于JVM。但是,当我们使用notifyAll()方法时,会收到多个线程的通知,但是线程的执行将一个接一个地执行,因为线程需要锁,并且一个对象只能使用一个锁。
  3. 线程的互换性:如果您所有的等待线程都可以互换(唤醒的顺序无关紧要),我们应该使用notify()。一个常见的例子是线程池。但是,在其他情况下,等待线程可能具有不同的用途并且应该能够并行运行,我们应该使用notifyAll()。一个示例是对共享资源的维护操作,其中多个线程在访问该资源之前正在等待操作完成。
  4. When to use notify() method and notifyAll()

  • 在互斥锁定的情况下,只有一个等待线程在得到通知后可以做一些有用的事情(在这种情况下,获取锁定)。在这种情况下,您宁愿使用notify()。正确实施后,您也可以在这种情况下使用notifyAll(),但是不必要地唤醒线程,它们无论如何都无法执行任何操作。
  • 在某些情况下,等待完成后,所有等待线程都可以采取有用的措施。一个示例是一组等待某个任务完成的线程。任务完成后,所有等待的线程都可以继续其业务。在这种情况下,您将使用notifyAll()同时唤醒所有等待的线程。

Applications of notify() and notifyAll()

  • 对共享资源的维护操作,其中多个线程在访问该资源之前正在等待操作完成;为此,我们应该选择notifyAll()。
  • 假设我们有一个生产者线程和一个消费者线程。生产者生产的每个“packet”应该由消费者消费。消费者将某些东西放入队列中,然后调用notify()。
  • 冗长的过程完成后,我们希望收到通知。您需要发出哔声和屏幕更新。该过程执行notifyAll()以通知beeping-thread和screen-update-thread。

参考:https://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again

相关用法


注:本文由纯净天空筛选整理自GeeksforGeeks大神的英文原创作品 Difference between notify() and notifyAll() in Java。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。