顯式鎖(四)Lock的等待通知機制Condition
阿新 • • 發佈:2018-03-02
lock == 等待隊列 urn 一個 AI 移除 等待時間 font
?? 任意一個Java對象,都擁有一組監視器方法(定義在根類Object上),主要包括:wait( )、wait(long timeout)、notify()、notifyAll()方法;這些方法與關鍵字synchronized結合使用,可以實現 隱式鎖的等待/通知機制。而顯示鎖Lock也實現了等待/通知機制;Condition接口也提供了類似Object的監視器方法,與Lock配合使用可以實現 顯式鎖的等待/通知機制,但是兩者在使用方式和功能特性有所差別。總得來說,Condition接口更加靈活,功能更多:
- Condition 接口是支持多個等待隊列,也稱為條件隊列,即根據不同的條件進入不同的等待隊列,相應的,用戶便可以只在指定的等待隊列上喚醒線程,而不是喚醒所有的線程。而 Object監視器 則只能有一個等待隊列。
- Condition 接口還提供了對中斷不敏感的等待方法,即當處於等待狀態時,是不會被中斷的。而Object監視器 不支持不可中斷的等待。
- Condition 接口除了提供了超時等待方法之外,還提供了等待直到將來某個時間段的方法;Object監視器只有超時等待的方法。
Condition 接口的方法:
方法名稱 | 描 述 |
---|---|
void await() throws InterruptedException | 造成當前線程在接到通知或被中斷之前一直處於等待狀態。即發生以下兩種情況,將會從await()方法返回: 1、其他某個線程調用此 Condition 的 signal()、signalAll()方法; 2、其他某個線程中斷當前線程 |
void awaitUninterruptibly() | 造成當前線程在接到通知之前一直處於等待狀態。 與await()方法相比,這是不可中斷的等待方法 |
long awaitNanos(long nanosTimeout) throws InterruptedException | 造成當前線程在接到通知、被中斷或到達指定等待時間之前一直處於等待狀態。 返回值:此方法返回時,距離超時的剩余時間,即返回值就是(nanosTimeout - 實際耗時);如果返回值是0或者負數,那麽認定已經超時 |
boolean await(long time, TimeUnit unit) throws InterruptedException | 造成當前線程在接到通知、被中斷或到達指定等待時間之前一直處於等待狀態。 返回值:如果在從此方法返回前檢測到等待時間超時(到達指定時間),則返回 false,否則返回 true 此方法在行為上等效於: awaitNanos(unit.toNanos(time)) > 0 |
boolean awaitUntil(Date deadline) throws InterruptedException | 造成當前線程在接到通知、被中斷或到達指定最後期限之前一直處於等待狀態。 返回值:如果在從此方法返回前檢測到等待時間超時(到達指定時間),則返回 false,否則返回 true |
void signal() | 喚醒一個等待線程。如果所有的線程都在等待此條件,則選擇其中的一個喚醒。在從 await 返回之前,該線程必須重新獲取鎖。 |
void signalAll() | 喚醒所有等待線程。 如果所有的線程都在等待此條件,則喚醒所有線程。在從 await 返回之前,每個線程都必須重新獲取鎖。 |
@ Example Condition 的例子
public class BoundedQueue<T> {
private Object[] item;
//添加的下標、刪除的下標、數組的當前數量
private int addIndex,removeIndex,count;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public BoundedQueue(int size){
item = new Object[size];
}
//添加一個元素,如果數組滿,則添加線程進入等待狀態,直到有空位
public void add(T t) throws InterruptedException{
lock.lock();
try{
while(count == item.length){
//可中斷的等待,如果沒有剩余空間,那麽就進入notFull的等待隊列
notFull.wait();
}
item[addIndex] = t;
if(++addIndex == item.length){//模擬環數組,一直插入,直到尾部,又重新從頭部插入
addIndex = 0;
}
count++;
//剛插入一個元素,不為空的條件滿足,可喚醒等待在notEmpty隊列上的線程
notEmpty.signal();
}finally {
lock.unlock();
}
}
//從頭部移除一個元素,如果數組為空,則等待,直到數組不為空
public T remove(){
lock.lock();
try{
while(count == 0){
//不可中斷的等待,不為空的條件不滿足,就會一直等待
notEmpty.awaitUninterruptibly();;
}
Object x = item[removeIndex];
if(++removeIndex == item.length){
removeIndex = 0;
}
count--;
//剛移除一個元素,數組沒有滿的條件符合,喚醒等待在notFull上的線程
notFull.signal();
return (T)x;
}finally{
lock.unlock();
}
}
}
顯式鎖(四)Lock的等待通知機制Condition