wait()方法與await()方法的區別

luorx發表於2024-11-19

wait() 方法與 await() 方法的區別

這兩種方法都與執行緒或非同步任務的協調有關,但它們用於不同的場景,並且行為和語法都不相同。


1. wait() 方法

定義與場景

  • 所屬java.lang.Object 類。

  • 用途:用於執行緒間的通訊,通常與 notify()notifyAll() 方法一起使用。

  • 場景:在多執行緒程式中,一個執行緒等待某些條件滿足,而另一個執行緒通知它繼續執行。

關鍵特點

  • 必須在同步塊(synchronized)或同步方法中呼叫,否則會丟擲 IllegalMonitorStateException

  • 呼叫 wait() 的執行緒會釋放鎖並進入 等待狀態,直到另一個執行緒呼叫 notify()notifyAll() 喚醒它。

  • 屬於阻塞操作,呼叫後執行緒會停止執行,直到被喚醒。

語法

synchronized (lock) {
    lock.wait();  // 釋放鎖並進入等待狀態
}

  

示例

class WaitNotifyExample {
    private static final Object lock = new Object();
​
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread 1 is waiting...");
                    lock.wait();
                    System.out.println("Thread 1 is resumed!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
​
        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Thread 2 is notifying...");
                lock.notify();
            }
        });
​
        t1.start();
        t2.start();
    }
}

  

輸出
Thread 1 is waiting...
Thread 2 is notifying...
Thread 1 is resumed!

2. await() 方法

定義與場景

所屬:java.util.concurrent.locks.Condition 介面。

用途:用於高階執行緒協調,通常結合 ReentrantLock 使用。

場景:細粒度控制執行緒的等待和喚醒操作,在併發程式設計中提供更靈活的機制。

關鍵特點
必須在鎖物件(如 ReentrantLock)的條件中使用,不能在普通的同步塊中使用。

與 wait() 類似,呼叫執行緒會釋放鎖並進入等待狀態,直到被其他執行緒透過 signal() 或 signalAll() 喚醒。

提供更好的執行緒通訊控制,可以使用多個條件(Condition),而不像 wait() 只能針對一個物件鎖。

語法
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
​
lock.lock();
try {
    condition.await(); // 釋放鎖並進入等待狀態
} finally {
    lock.unlock();
}
  

示例
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
​
class AwaitSignalExample {
    private static final ReentrantLock lock = new ReentrantLock();
    private static final Condition condition = lock.newCondition();
​
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 1 is waiting...");
                condition.await();
                System.out.println("Thread 1 is resumed!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
​
        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread 2 is signaling...");
                condition.signal();
            } finally {
                lock.unlock();
            }
        });
​
        t1.start();
        t2.start();
    }
}

  

輸出

Thread 1 is waiting...
Thread 2 is signaling...
Thread 1 is resumed!

對比總結

特性wait()await()
所屬類 java.lang.Object java.util.concurrent.locks.Condition
使用鎖型別 Java 內建鎖(synchronized 顯式鎖(ReentrantLock
等待/喚醒方法 wait() / notify() / notifyAll() await() / signal() / signalAll()
是否釋放鎖 釋放鎖,等待被通知 釋放鎖,等待被通知
靈活性 只能使用一個物件鎖,功能較為簡單 可以為不同條件建立多個 Condition,功能更強大
執行緒安全控制粒度 粒度較粗 粒度更細
是否支援中斷 可以透過 InterruptedException 被中斷 同樣支援 InterruptedException

選擇建議

  • wait()

    • 如果是傳統的 synchronized 程式碼塊,使用 wait() 即可。

    • 適合簡單的執行緒間協調。

  • await()

    • 如果需要更復雜的執行緒控制(如多個條件或高階同步機制),推薦使用 await()ReentrantLock

    • 更適合高併發場景。

相關文章