前言
從之前的阻塞隊列的源碼分析中,我們知道,JDK 中的阻塞隊列是使用 ReentrantLock 和 Condition 實現了,我們今天來個簡易版的。代碼如下:
代碼
public class BoundedBuffer {
final ReentrantLock lock = new ReentrantLock();
final ConditionObject notFull = (ConditionObject) lock.newCondition();
final ConditionObject notEmpty = (ConditionObject) 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) {
// 釋放鎖,等待
notFull.await();
}
// 放入數據
items[putptr] = x;
// 如果到最后一個位置了,下標從頭開始,防止下標越界
if (++putptr == items.length) {
// 從頭開始
putptr = 0;
}
// 對 count ++ 加加
++count;
// 通知 take 線程,可以取數據了,不必繼續阻塞
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
// 如果數組沒有數據,則等待
while (count == 0) {
notEmpty.await();
}
// 取數據
Object x = items[takeptr];
// 如果到數組盡頭了,就從頭開始
if (++takeptr == items.length) {
// 從頭開始
takeptr = 0;
}
// 將數量減1
--count;
// 通知阻塞的 put 線程可以裝填數據了
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
其實,這並不是我寫的,而是 Condition 接口的 JavaDoc 文檔中寫的。並且文檔中說,請不要再次實現這個隊列,因為 JDK 內部已經是實現了。原話如下:
(The {@link java.util.concurrent.ArrayBlockingQueue} class provides this functionality, so there is no reason to implement this sample usage class.)
樓主只是覺得這個代碼寫的挺好的,所以分享一下,其中關鍵的還是 Condition 和重入鎖,重入鎖的核心源碼我們已經看過了,今天來看看 Condition 的源碼。所以我們今天使用了這個代碼作為一個入口。
可以看到,Condition 的重要方法就是 await 和 signal,類似 Object 類的 wait 和 notify 方法。
我們后面會詳細講講這兩個方法的實現。