摘要:造成當(dāng)前線程在接到信號被中斷或到達(dá)指定最后期限之前一直處于等待狀態(tài)。我們喜歡在多帶帶的等待中保存線程和線程,這樣就可以在緩沖區(qū)中的項(xiàng)或空間變得可用時利用最佳規(guī)劃,一次只通知一個線程。
Condition接口
Condition的功能類似于傳統(tǒng)線程技術(shù)中的Object.wait()和Object.notify()方法的功能,但它是將這些方法分解成不同的對象,所以可以將這些對象與任意的Lock實(shí)現(xiàn)組合使用,實(shí)現(xiàn)在不同的條件下阻塞或喚醒線程;也就是說,這其中的Lock替代了synchronized方法和語句的使用,Condition替代了Object 監(jiān)視器方法(wait、notify 和 notifyAll)的使用。創(chuàng)建一個Condition
Condition需要被綁定在一個鎖(Lock)上,所以如果要為一個Lock實(shí)例獲得Condition實(shí)例,可以使用Lock的newCondition() 方法。
Condition notFull = lock.newCondition();Condition接口的常用方法
void await()代碼示例
造成當(dāng)前線程在接到信號或被中斷之前一直處于等待狀態(tài)。
boolean await(long time, TimeUnit unit)
造成當(dāng)前線程在接到信號、被中斷或到達(dá)指定等待時間之前一直處于等待狀態(tài)。
long awaitNanos(long nanosTimeout)
造成當(dāng)前線程在接到信號、被中斷或到達(dá)指定等待時間之前一直處于等待狀態(tài)。
void awaitUninterruptibly()
造成當(dāng)前線程在接到信號之前一直處于等待狀態(tài)。
boolean awaitUntil(Date deadline)
造成當(dāng)前線程在接到信號、被中斷或到達(dá)指定最后期限之前一直處于等待狀態(tài)。
void signal()
喚醒一個等待線程。
void signalAll()
喚醒所有等待線程。
這段代碼是JDK API文檔中提供的示例,假定有一個綁定的緩沖區(qū),它支持 put 和 take 方法。如果試圖在空的緩沖區(qū)上執(zhí)行 take 操作,則在某一個項(xiàng)變得可用之前,線程將一直阻塞;如果試圖在滿的緩沖區(qū)上執(zhí)行 put 操作,則在有空間變得可用之前,線程將一直阻塞。我們喜歡在多帶帶的等待 set 中保存 put 線程和 take 線程,這樣就可以在緩沖區(qū)中的項(xiàng)或空間變得可用時利用最佳規(guī)劃,一次只通知一個線程。可以使用兩個 Condition 實(shí)例來做到這一點(diǎn)。
public class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) { //當(dāng)緩沖區(qū)已滿時,notFull阻塞 notFull.await(); } //否則將元素添加進(jìn)緩沖區(qū)的下標(biāo)位置 items[putptr] = x; if (++putptr == items.length) { //如果下一個下標(biāo)越界,則將下標(biāo)移至緩沖區(qū)首位 putptr = 0; } //count表示緩沖區(qū)中元素個數(shù) ++count; //由于緩沖已經(jīng)是notEmpty狀態(tài),所以喚醒阻塞等待的notEmpty notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) { //當(dāng)緩沖區(qū)中沒有元素,緩沖區(qū)處于empty狀態(tài),所以notEmpty阻塞 notEmpty.await(); } Object x = items[takeptr]; if (++takeptr == items.length) { //獲得下標(biāo)位置的元素后,將下標(biāo)向前移動,如果移動后的下標(biāo)越界,則將下標(biāo)移至緩沖區(qū)首位 takeptr = 0; } --count; //取出一個元素后,緩沖區(qū)處于notFull狀態(tài),所以喚醒阻塞等待的notFull notFull.signal(); return x; } finally { lock.unlock(); } } }注意:
和監(jiān)視器方法一樣,Condition也可能發(fā)生“虛假喚醒”,所以Condition必須在總是在一個循環(huán)中被等待,并在被喚醒后測試當(dāng)前狀態(tài),判斷當(dāng)前是否已經(jīng)處于可以被喚醒的狀態(tài),我們需要假定“虛假喚醒”可能發(fā)生。
while (count == 0) { //在循環(huán)中等待 condition.await(); }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/68809.html
摘要:提供了多線程升級方案將同步替換成了顯示的操作。線程間通信接口可以替代傳統(tǒng)的線程間通信,用替換,用替換,用替換。商品執(zhí)行上述代碼,觀察結(jié)果可以看到,多個線程同時生產(chǎn)消費(fèi),由于指定喚醒互異線程,因此并不會引起錯誤。 JDK 1.5提供了多線程升級方案將同步synchronized替換成了顯示的Lock操作。可以實(shí)現(xiàn)喚醒、凍結(jié)指定的線程。 Lock接口Lock 實(shí)現(xiàn)提供了比使用 synchr...
摘要:本文對多線程基礎(chǔ)知識進(jìn)行梳理,主要包括多線程的基本使用,對象及變量的并發(fā)訪問,線程間通信,的使用,定時器,單例模式,以及線程狀態(tài)與線程組。源碼采用構(gòu)建,多線程這部分源碼位于模塊中。通知可能等待該對象的對象鎖的其他線程。 本文對多線程基礎(chǔ)知識進(jìn)行梳理,主要包括多線程的基本使用,對象及變量的并發(fā)訪問,線程間通信,lock的使用,定時器,單例模式,以及線程狀態(tài)與線程組。 寫在前面 花了一周時...
摘要:二接口簡介可以看做是類的方法的替代品,與配合使用。當(dāng)線程執(zhí)行對象的方法時,當(dāng)前線程會立即釋放鎖,并進(jìn)入對象的等待區(qū),等待其它線程喚醒或中斷。 showImg(https://segmentfault.com/img/remote/1460000016012601); 本文首發(fā)于一世流云的專欄:https://segmentfault.com/blog... 本系列文章中所說的juc-...
摘要:無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執(zhí)行單元獲得鎖。另外在中引入了自適應(yīng)的自旋鎖。和關(guān)鍵字的總結(jié)推薦一 該文已加入開源文檔:JavaGuide(一份涵蓋大部分Java程序員所需要掌握的核心知識)。地址:https://github.com/Snailclimb... 本文是對 synchronized 關(guān)鍵字使用、底層原理、JD...
閱讀 2070·2021-10-11 10:59
閱讀 930·2021-09-23 11:21
閱讀 3555·2021-09-06 15:02
閱讀 1615·2021-08-19 10:25
閱讀 3371·2021-07-30 11:59
閱讀 2366·2019-08-30 11:27
閱讀 2581·2019-08-30 11:20
閱讀 2970·2019-08-29 13:15