Java Condition條件變量提高線程通信效率
條件(也稱為條件隊列 或條件變量)為線程提供了一個含義,以便在某個狀態(tài)條件現(xiàn)在可能為 true 的另一個線程通知它之前,一直掛起該線程(即讓其“等待”)。因為訪問此共享狀態(tài)信息發(fā)生在不同的線程中,所以它必須受保護,因此要將某種形式的鎖與該條件相關聯(lián)。等待提供一個條件的主要屬性是:以原子方式 釋放相關的鎖,并掛起當前線程,就像 Object.wait 做的那樣
在Condition中,用await()替換wait(),用signal()替換notify(),用signalAll()替換notifyAll(),傳統(tǒng)線程的通信方式,Condition都可以實現(xiàn)。
條件變量類似JDK1.4或以前版本中的 Object.wait(); Object.notify(); Object.notifyAll();
值得注意的是當condition.await()時,隱式的將條件變量關聯(lián)的Lock解鎖,而使其他線程有機會獲得Lock,而檢查條件,并在條件滿足時,等待在條件變量上。
示例代碼,ArrayBlockingQueue源碼摘?。?/p>
/** 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(); } }
有多個線程往里面存數(shù)據(jù)和從里面取數(shù)據(jù),其隊列(先進先出后進后出)能緩存的最大數(shù)值是capacity,多個線程間是互斥的,當緩存隊列中存儲的值達到capacity時,將寫線程阻塞,并喚醒讀線程,當緩存隊列中存儲的值為0時,將讀線程阻塞,并喚醒寫線程
這就是多個Condition的強大之處,假設緩存隊列中已經(jīng)存滿,那么阻塞的肯定是寫線程,喚醒的肯定是讀線程,相反,阻塞的肯定是讀線程,喚醒的肯定是寫線程,那么假設只有一個Condition會有什么效果呢,緩存隊列中已經(jīng)存滿,這個Lock不知道喚醒的是讀線程還是寫線程了,如果喚醒的是讀線程,皆大歡喜,如果喚醒的是寫線程,那么線程剛被喚醒,又被阻塞了,這時又去喚醒,這樣就浪費了很多時間!
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
@valid 無法觸發(fā)BindingResult的解決
這篇文章主要介紹了@valid 無法觸發(fā)BindingResult的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12淺談java switch如果case后面沒有break,會出現(xiàn)什么情況?
這篇文章主要介紹了淺談java switch如果case后面沒有break,會出現(xiàn)什么情況?具有很好的參考價值,希望對大家有所幫助。一起跟隨想小編過來看看吧2020-09-09SpringBoot集成Mybatis的實現(xiàn)步驟
這篇文章主要介紹了SpringBoot集成Mybatis的實現(xiàn)步驟,本文通過SpringBoot +MyBatis 實現(xiàn)對數(shù)據(jù)庫學生表的查詢操作,需要的朋友可以參考下2020-12-12SSH框架網(wǎng)上商城項目第15戰(zhàn)之線程、定時器同步首頁數(shù)據(jù)
這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第15戰(zhàn)之線程、定時器同步首頁數(shù)據(jù),感興趣的小伙伴們可以參考一下2016-06-06