本篇內(nèi)容基于JDK7,涉及Condition常用方法致扯。
1.概述
Condition接口位于java.util.concurrent.locks包下届吁,實(shí)現(xiàn)類有
AbstractQueuedLongSynchronizer.ConditionObject和
AbstractQueuedSynchronizer.ConditionObject。Condition將Object監(jiān)視器方法(wait维雇、notify和 notifyAll)分解成截然不同的對象赊舶,以便通過將這些對象與任意Lock實(shí)現(xiàn)組合使用睁搭。其中赶诊,Lock替代了synchronized方法的使用及作用,Condition替代了Object監(jiān)視器方法的使用及作用园骆。Condition的await方法代替Object的wait舔痪;Condition的signal方法代替Object的notify方法;Condition的signalAll方法代替Object的notifyAll方法锌唾。Condition實(shí)例在使用時(shí)需要綁定到一個(gè)鎖上锄码,可以通過newCondition方法獲取Condition實(shí)例。Condition實(shí)現(xiàn)可以提供不同于Object監(jiān)視器方法的行為和語義晌涕,比如受保證的通知排序滋捶,或者在執(zhí)行通知時(shí)不需要保持一個(gè)鎖。
2.使用樣例
下面的代碼演示了Condition簡單使用的樣例余黎。
public class ConditionDemo {
@Test
public void test() {
final ReentrantLock reentrantLock = new ReentrantLock();
final Condition condition = reentrantLock.newCondition();
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
System.out.println(Thread.currentThread().getName() + "在等待被喚醒");
condition.await();
System.out.println(Thread.currentThread().getName() + "恢復(fù)執(zhí)行了");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
System.out.println(Thread.currentThread().getName() + "搶到了鎖");
condition.signal();
System.out.println(Thread.currentThread().getName() + "喚醒其它等待的線程");
} catch (Exception e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
}, "thread2").start();
}
}
輸出結(jié)果如下所示:
thread1在等待被喚醒
thread2搶到了鎖
thread2喚醒其它等待的線程
thread1恢復(fù)執(zhí)行了
3.創(chuàng)建Condition實(shí)例
通過Lock接口實(shí)現(xiàn)類的newCondition方法獲取Condition實(shí)例重窟,例如如下代碼:
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition = reentrantLock.newCondition();
4.常用方法
4.1 await()
調(diào)用await方法后,當(dāng)前線程在接收到喚醒信號(hào)之前或被中斷之前一直處于等待休眠狀態(tài)惧财。調(diào)用此方法時(shí)巡扇,當(dāng)前線程保持了與此Condition有關(guān)聯(lián)的鎖,調(diào)用此方法后可缚,當(dāng)前線程釋放持有的鎖霎迫。此方法可以返回當(dāng)前線程之前斋枢,都必須重新獲取與此條件有關(guān)的鎖帘靡,在線程返回時(shí),可以保證它保持此鎖瓤帚。
4.2 await(long time,TimeUnit unit)
調(diào)用此方法后描姚,會(huì)造成當(dāng)前線程在接收到喚醒信號(hào)之前、被中斷之前或到達(dá)指定等待時(shí)間之前一直處于等待狀態(tài)戈次。調(diào)用此方法時(shí)轩勘,當(dāng)前線程保持了與此Condition有關(guān)聯(lián)的鎖,調(diào)用此方法后怯邪,當(dāng)前線程釋放持有的鎖绊寻。time參數(shù)為最長等待時(shí)間;unit參數(shù)為time的時(shí)間單位悬秉。如果在從此方法返回前檢測到等待時(shí)間超時(shí)澄步,則返回 false,否則返回true和泌。此方法可以返回當(dāng)前線程之前村缸,都必須重新獲取與此條件有關(guān)的鎖,在線程返回時(shí)武氓,可以保證它保持此鎖梯皿。
4.3 awaitNanos(long nanosTimeout)
該方法等效于await(long time,TimeUnit unit)方法仇箱,只是等待的時(shí)間是
nanosTimeout指定的以毫微秒數(shù)為單位的等待時(shí)間。該方法返回值是所剩毫微秒數(shù)的一個(gè)估計(jì)值东羹,如果超時(shí)剂桥,則返回一個(gè)小于等于0的值∈籼幔可以根據(jù)該返回值來確定是否要再次等待渊额,以及再次等待的時(shí)間。
4.4 awaitUninterruptibly()
調(diào)用此方法后垒拢,會(huì)造成當(dāng)前線程在接收到喚醒信號(hào)之前一直處于等待狀態(tài)旬迹。如果在進(jìn)入此方法時(shí)設(shè)置了當(dāng)前線程的中斷狀態(tài),或者在等待時(shí)求类,線程被中斷奔垦,那么在接收到喚醒信號(hào)之前,它將繼續(xù)等待尸疆。當(dāng)最終從此方法返回時(shí)椿猎,仍然將設(shè)置其中斷狀態(tài)。調(diào)用此方法時(shí)寿弱,當(dāng)前線程保持了與此Condition有關(guān)聯(lián)的鎖犯眠,調(diào)用此方法后,當(dāng)前線程釋放持有的鎖症革。此方法可以返回當(dāng)前線程之前筐咧,都必須重新獲取與此條件有關(guān)的鎖,在線程返回時(shí)噪矛,可以保證它保持此鎖量蕊。
4.5 awaitUntil(Date deadline)
調(diào)用此方法后,會(huì)造成當(dāng)前線程在接收到喚醒信號(hào)之前艇挨、被中斷之前或到達(dá)指定最后期限之前一直處于等待休眠狀態(tài)残炮。調(diào)用此方法時(shí),當(dāng)前線程保持了與此Condition有關(guān)聯(lián)的鎖缩滨,調(diào)用此方法后势就,當(dāng)前線程釋放持有的鎖。此方法可以返回當(dāng)前線程之前脉漏,都必須重新獲取與此條件有關(guān)的鎖苞冯,在線程返回時(shí),可以保證它保持此鎖鸠删。
4.6 signal()
喚醒一個(gè)等待線程抱完,如果所有的線程都在等待此條件,則選擇其中的一個(gè)喚醒刃泡。在從await返回之前巧娱,該線程必須重新獲取鎖碉怔。
4.7 signalAll()
喚醒所有等待線程,如果所有的線程都在等待此條件禁添,則喚醒所有線程撮胧。 在從await返回之前,每個(gè)線程必須重新獲取鎖老翘。