Condition 將 Object 監視器方法(wait、notify、notifyAll)解耦為獨立對象,配合 Lock 實現更靈活的多等待隊列控制。Lock 替代 synchronized,Condition 替代 Object 監視器方法。
public class ConditionTest {
public static void main(String[] args) {
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
Thread thread1 = new Thread(() -> {
try {
lock.lock();
System.out.println("線程1:等待信號 " + Thread.currentThread());
condition.await(); // 釋放鎖並阻塞
System.out.println("線程1:收到信號 " + Thread.currentThread());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "thread1");
thread1.start();
Thread thread2 = new Thread(() -> {
try {
lock.lock();
System.out.println("線程2:獲得鎖");
Thread.sleep(500);
System.out.println("線程2:發送信號");
condition.signal(); // 喚醒一個等待線程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "thread2");
thread2.start();
}
}
線程1:等待信號 Thread[thread1,5,main] 線程2:獲得鎖 線程2:發送信號 線程1:收到信號 Thread[thread1,5,main]

流程解析:
thread1 獲取鎖,調用 await() 釋放鎖並進入等待隊列。thread2 獲取鎖,休眠 500ms 模擬處理,調用 signal() 喚醒 thread1。thread1 重新獲取鎖,從 await() 返回繼續執行。| 方法 | 說明 |
|---|---|
await() | 當前線程釋放鎖並阻塞,直到被 signal()/signalAll() 喚醒或中斷 |
signal() | 喚醒一個等待在該 Condition 上的線程 |
signalAll() | 喚醒所有等待線程 |
awaitNanos(timeout) | 帶超時的等待,返回剩餘納秒數 |
public class BoundedQueue<T> {
private final Object[] items;
private int putIdx, takeIdx, count;
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public BoundedQueue(int capacity) { items = new Object[capacity]; }
public void put(T t) throws InterruptedException {
lock.lock();
try {
while (count == items.length) notFull.await(); // 滿則等待
items[putIdx] = t;
if (++putIdx == items.length) putIdx = 0;
++count;
notEmpty.signal(); // 通知消費者
} finally { lock.unlock(); }
}
@SuppressWarnings("unchecked")
public T take() throws InterruptedException {
lock.lock();
try {
while (count == 0) notEmpty.await(); // 空則等待
T t = (T) items[takeIdx];
items[takeIdx] = null;
if (++takeIdx == items.length) takeIdx = 0;
--count;
notFull.signal(); // 通知生產者
return t;
} finally { lock.unlock(); }
}
}
使用兩個 Condition(notFull、notEmpty)分別控制生產與消費等待隊列,實現精確喚醒,避免 notifyAll() 的驚群效應。