當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Java notify()和notifyAll()的區別用法及代碼示例


notify() 和notifyAll() 方法以及wait() 方法用於線程之間的通信。通過調用 wait() 方法進入等待狀態的線程將處於等待狀態,直到任何其他線程在同一對象上調用 notify() 或 notifyAll() 方法。

notify(): notify()方法定義在對象類,這是Java的頂級類。它隻用於喚醒一個它正在等待一個對象,然後該線程開始執行。線程類notify()方法用於喚醒單個線程。

notifyAll():notifyAll() 喚醒在此對象監視器上等待的所有線程。線程通過調用其中之一來等待對象的監視器等待方法。被喚醒的線程將無法繼續,直到當前線程放棄該對象上的鎖。

現在的問題是notify()和notifyAll()方法都用於向等待線程發出通知,那麽它們之間有什麽區別或者我們應該在哪裏使用notify()方法以及我們應該在哪裏使用notifyAll()方法?

先生。沒有。 鑰匙 notify() notifyAll()
1 Notifications multiThreading 的情況下,notify() 方法僅將通知發送到等待發送鎖的多個等待線程中的一個線程。 而同一上下文中的 notifyAll() 方法將通知發送給所有等待線程而不是單個線程。
2 線程標識 與notify()方法的情況一樣,通知被發送到多個等待線程中的單個線程,因此可以確定哪些等待線程將接收鎖。 另一方麵,notifyAll() 向所有等待線程發送通知。因此,不清楚哪個線程將接收鎖。
3 風險因子 在notify()方法的情況下,線程丟失的風險很高,因為通知僅發送給單個線程,如果它丟失了,那麽其他線程將不會收到通知,從而獲得鎖。 而在 notifyAll() 的情況下,它會向所有等待線程發送通知,因此如果任何線程錯過了通知,就會有其他線程來完成這項工作。因此風險較小。
4 Performance 與 notifyAll() 方法相比,MemoryCPU 在 notify() 方法中消耗更少,因為通知發送到單個線程,因此與 notifyAll() 相比性能更好。 另一方麵,沒有通知的成本被降低,通知被發送到所有等待線程,與 notify() 相比,內存和 CPU 消耗更多,因此 notifyAll() 的性能較低。
5 Interchangeable 在notify()方法的情況下,圖中隻有一個線程,因此不可能存在線程可互換的概念。 如果所有等待線程都可以互換(它們喚醒的順序並不重要),那麽我們應該選擇notifyAll()。

讓我們了解notify()方法的行為方式:

Java


// 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


// 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-1...notified
Thread-2...notified

When to Use notify() method and notifyAll()?

  • 在互斥鎖定的情況下,隻有一個等待線程在收到通知後可以執行一些有用的操作(在本例中獲取鎖)。在這種情況下,您寧願使用notify()。如果實現得當,您也可以在這種情況下使用notifyAll(),但您會不必要地喚醒無論如何都無法執行任何操作的線程。
  • 在某些情況下,一旦等待完成,所有等待線程都可以采取有用的操作。一個例子是一組線程等待某個任務完成;一旦任務完成,所有等待線程就可以繼續其業務。在這種情況下,您可以使用notifyAll()同時喚醒所有等待線程。

Applications of notify() and notifyAll()

  • 對共享資源的維護操作,其中多個線程在訪問資源之前等待操作完成;對於這些,我們應該選擇notifyAll()。
  • 假設我們有一個生產者線程和一個消費者線程。生產者生產的每個 “packet” 都應該由消費者消費。消費者將一些東西放入隊列中,然後調用notify()。
  • 我們希望在漫長的過程完成時收到通知。您需要蜂鳴聲和屏幕更新。該進程執行notifyAll()來通知蜂鳴線程和screen-update-thread。


相關用法


注:本文由純淨天空篩選整理自佚名大神的英文原創作品 Difference Between notify() and notifyAll() in Java。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。