ArrayBlockingQueue
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
//一把鎖管理
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
put
public void put(E e) throws InterruptedException {
//value不允許爲null
checkNotNull(e);
final ReentrantLock lock = this.lock;
//中斷鎖
lock.lockInterruptibly();
try {
//當前count超過生產的容量上限,則等待
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
//釋放鎖
lock.unlock();
}
}
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x;
//當前個數超過下標,則回滾爲0下標
if (++putIndex == items.length)
putIndex = 0;
//當前可進行消息個數+1
count++;
//喚醒消費線程進行消費
notEmpty.signal();
}
offer
public boolean offer(E e) {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
//當前消息個數超過上限,則直接返回
if (count == items.length)
return false;
else {
enqueue(e);
return true;
}
} finally {
lock.unlock();
}
}
take
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
//當前沒有消息,則等待
while (count == 0)
notEmpty.await();
//消費消息
return dequeue();
} finally {
lock.unlock();
}
}
private E dequeue() {
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null;
final Object[] items = this.items;
@SuppressWarnings("unchecked")
//獲取消息
E x = (E) items[takeIndex];
//清空消息
items[takeIndex] = null;
//當前消費的索引爲數組長度,則從0開始消費消息
if (++takeIndex == items.length)
takeIndex = 0;
count--;
//迭代器衝突處理
if (itrs != null)
itrs.elementDequeued();
//喚醒生產線程,生產消息
notFull.signal();
return x;
}
void elementDequeued() {
// assert lock.getHoldCount() == 1;
//消費個數爲0,則清空迭代器值
if (count == 0)
queueIsEmpty();
else if (takeIndex == 0)
//消費的索引回滾爲0處理
takeIndexWrapped();
}
remove
public boolean remove(Object o) {
if (o == null) return false;
final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
final int putIndex = this.putIndex;
int i = takeIndex;
//遍歷takeIndex ~ putIndex之間的數據,如果涉及到邊界問題,則從0開始查找
do {
//匹配則刪除
if (o.equals(items[i])) {
removeAt(i);
return true;
}
//邊界檢測.
if (++i == items.length)
i = 0;
} while (i != putIndex);
}
return false;
} finally {
lock.unlock();
}
}
void removeAt(final int removeIndex) {
// assert lock.getHoldCount() == 1;
// assert items[removeIndex] != null;
// assert removeIndex >= 0 && removeIndex < items.length;
final Object[] items = this.items;
//如果刪除的消息和目前正take索引相同
if (removeIndex == takeIndex) {
// removing front item; just advance
//清空當前take消息
items[takeIndex] = null;
//takeIndex偏移到下一個
if (++takeIndex == items.length)
takeIndex = 0;
count--;
//迭代器衝突處理
if (itrs != null)
itrs.elementDequeued();
} else {
// an "interior" remove
// slide over all others up through putIndex.
final int putIndex = this.putIndex;
for (int i = removeIndex;;) {
int next = i + 1;
//達到數組上線,索引設爲0,開始遍歷
if (next == items.length)
next = 0;
//未到邊界,則偏移到下一個數組值
if (next != putIndex) {
items[i] = items[next];
i = next;
} else {
//到了邊界,設置當前items[putIndex]值爲null,且更新putIndex
items[i] = null;
this.putIndex = i;
break;
}
}
//當前消息個數-1
count--;
//迭代器衝突處理
if (itrs != null)
itrs.removedAt(removeIndex);
}
notFull.signal();
}
總結
有界阻塞隊列。此隊列按 FIFO(先進先出)原則對元素進行排序。
初始化必須設置容量,value不允許爲空
全局一個鎖處理,相對併發比較低.
因爲底層數組,所以修改查詢快.