1. 程式人生 > 程式設計 >Java Condition條件變數提高執行緒通訊效率

Java Condition條件變數提高執行緒通訊效率

條件(也稱為條件佇列 或條件變數)為執行緒提供了一個含義,以便在某個狀態條件現在可能為 true 的另一個執行緒通知它之前,一直掛起該執行緒(即讓其“等待”)。因為訪問此共享狀態資訊發生在不同的執行緒中,所以它必須受保護,因此要將某種形式的鎖與該條件相關聯。等待提供一個條件的主要屬性是:以原子方式 釋放相關的鎖,並掛起當前執行緒,就像 Object.wait 做的那樣

在Condition中,用await()替換wait(),用signal()替換notify(),用signalAll()替換notifyAll(),傳統執行緒的通訊方式,Condition都可以實現。

條件變數類似JDK1.4或以前版本中的 Object.wait(); Object.notify(); Object.notifyAll();

值得注意的是當condition.await()時,隱式的將條件變數關聯的Lock解鎖,而使其他執行緒有機會獲得Lock,而檢查條件,並在條件滿足時,等待在條件變數上。

示例程式碼,ArrayBlockingQueue原始碼摘取:

/** Main lock guarding all access */
private final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
/**
 * Inserts the specified element at the tail of this queue,waiting
 * for space to become available if the queue is full.
 *
 * @throws InterruptedException {@inheritDoc}
 * @throws NullPointerException {@inheritDoc}
 */
public void put(E e) throws InterruptedException {
 if (e == null) throw new NullPointerException();
 final E[] items = this.items;
 final ReentrantLock lock = this.lock;
 lock.lockInterruptibly();
 try {
 try {
  while (count == items.length)
  notFull.await();
 } catch (InterruptedException ie) {
  notFull.signal(); // propagate to non-interrupted thread
  throw ie;
 }
 insert(e);
 } finally {
 lock.unlock();
 }
}
public E take() throws InterruptedException {
 final ReentrantLock lock = this.lock;
 lock.lockInterruptibly();
 try {
 try {
  while (count == 0)
  notEmpty.await();
 } catch (InterruptedException ie) {
  notEmpty.signal(); // propagate to non-interrupted thread
  throw ie;
 }
 E x = extract();
 return x;
 } finally {
 lock.unlock();
 }
}

有多個執行緒往裡面存資料和從裡面取資料,其佇列(先進先出後進後出)能快取的最大數值是capacity,多個執行緒間是互斥的,當快取佇列中儲存的值達到capacity時,將寫執行緒阻塞,並喚醒讀執行緒,當快取佇列中儲存的值為0時,將讀執行緒阻塞,並喚醒寫執行緒
這就是多個Condition的強大之處,假設快取佇列中已經存滿,那麼阻塞的肯定是寫執行緒,喚醒的肯定是讀執行緒,相反,阻塞的肯定是讀執行緒,喚醒的肯定是寫執行緒,那麼假設只有一個Condition會有什麼效果呢,快取佇列中已經存滿,這個Lock不知道喚醒的是讀執行緒還是寫執行緒了,如果喚醒的是讀執行緒,皆大歡喜,如果喚醒的是寫執行緒,那麼執行緒剛被喚醒,又被阻塞了,這時又去喚醒,這樣就浪費了很多時間!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。