本篇內容基于JDK7,涉及Condition常用方法。
1.概述
Condition接口位于java.util.concurrent.locks包下,實現類有
AbstractQueuedLongSynchronizer.ConditionObject和
AbstractQueuedSynchronizer.ConditionObject。Condition將Object監視器方法(wait、notify和 notifyAll)分解成截然不同的對象,以便通過將這些對象與任意Lock實現組合使用。其中,Lock替代了synchronized方法的使用及作用,Condition替代了Object監視器方法的使用及作用。Condition的await方法代替Object的wait;Condition的signal方法代替Object的notify方法;Condition的signalAll方法代替Object的notifyAll方法。Condition實例在使用時需要綁定到一個鎖上,可以通過newCondition方法獲取Condition實例。Condition實現可以提供不同于Object監視器方法的行為和語義,比如受保證的通知排序,或者在執行通知時不需要保持一個鎖。
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() + "恢復執行了");
} 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();
}
}
輸出結果如下所示:
thread1在等待被喚醒
thread2搶到了鎖
thread2喚醒其它等待的線程
thread1恢復執行了
3.創建Condition實例
通過Lock接口實現類的newCondition方法獲取Condition實例,例如如下代碼:
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition = reentrantLock.newCondition();
4.常用方法
4.1 await()
調用await方法后,當前線程在接收到喚醒信號之前或被中斷之前一直處于等待休眠狀態。調用此方法時,當前線程保持了與此Condition有關聯的鎖,調用此方法后,當前線程釋放持有的鎖。此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖,在線程返回時,可以保證它保持此鎖。
4.2 await(long time,TimeUnit unit)
調用此方法后,會造成當前線程在接收到喚醒信號之前、被中斷之前或到達指定等待時間之前一直處于等待狀態。調用此方法時,當前線程保持了與此Condition有關聯的鎖,調用此方法后,當前線程釋放持有的鎖。time參數為最長等待時間;unit參數為time的時間單位。如果在從此方法返回前檢測到等待時間超時,則返回 false,否則返回true。此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖,在線程返回時,可以保證它保持此鎖。
4.3 awaitNanos(long nanosTimeout)
該方法等效于await(long time,TimeUnit unit)方法,只是等待的時間是
nanosTimeout指定的以毫微秒數為單位的等待時間。該方法返回值是所剩毫微秒數的一個估計值,如果超時,則返回一個小于等于0的值。可以根據該返回值來確定是否要再次等待,以及再次等待的時間。
4.4 awaitUninterruptibly()
調用此方法后,會造成當前線程在接收到喚醒信號之前一直處于等待狀態。如果在進入此方法時設置了當前線程的中斷狀態,或者在等待時,線程被中斷,那么在接收到喚醒信號之前,它將繼續等待。當最終從此方法返回時,仍然將設置其中斷狀態。調用此方法時,當前線程保持了與此Condition有關聯的鎖,調用此方法后,當前線程釋放持有的鎖。此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖,在線程返回時,可以保證它保持此鎖。
4.5 awaitUntil(Date deadline)
調用此方法后,會造成當前線程在接收到喚醒信號之前、被中斷之前或到達指定最后期限之前一直處于等待休眠狀態。調用此方法時,當前線程保持了與此Condition有關聯的鎖,調用此方法后,當前線程釋放持有的鎖。此方法可以返回當前線程之前,都必須重新獲取與此條件有關的鎖,在線程返回時,可以保證它保持此鎖。
4.6 signal()
喚醒一個等待線程,如果所有的線程都在等待此條件,則選擇其中的一個喚醒。在從await返回之前,該線程必須重新獲取鎖。
4.7 signalAll()
喚醒所有等待線程,如果所有的線程都在等待此條件,則喚醒所有線程。 在從await返回之前,每個線程必須重新獲取鎖。