1、ArrayBlockingQueue的成員變量
//存儲(chǔ)結(jié)構(gòu)是數(shù)組
final Object[] items;
//取數(shù)據(jù)指針
int takeIndex;
//存數(shù)據(jù)指針
int putIndex;
//數(shù)據(jù)最大長(zhǎng)度
int count;
//存取數(shù)據(jù)用的鎖
final ReentrantLock lock;
//隊(duì)列為空的阻塞條件
private final Condition notEmpty;
//隊(duì)列滿的阻塞條件
private final Condition notFull;
2窄俏、ArrayBlockingQueue的構(gòu)造器
//初始化固定大小的隊(duì)列
public ArrayBlockingQueue(int capacity);
//fair代表ReentrantLock的公平鎖與非公平鎖
public ArrayBlockingQueue(int capacity, boolean fair);
//Collection<? extends E> c可以傳入一個(gè)集合進(jìn)行構(gòu)造
public ArrayBlockingQueue(int capacity, boolean fair,Collection<? extends E> c)
3蹂匹、put方法(添加數(shù)據(jù),隊(duì)列滿則阻塞)
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
//可中斷的鎖
lock.lockInterruptibly();
try {
//如果隊(duì)列總長(zhǎng)度==items數(shù)組的長(zhǎng)度凹蜈,則需要進(jìn)行阻塞
while (count == items.length)
notFull.await();
//入隊(duì)操作
enqueue(e);
} finally {
lock.unlock();
}
}
private void enqueue(E x) {
final Object[] items = this.items;
//賦值
items[putIndex] = x;
//這里會(huì)對(duì)putIndex進(jìn)行++操作限寞。
//所以putIndex始終對(duì)應(yīng)著應(yīng)該插入元素的位置。
//當(dāng)++putIndex == items.length時(shí)仰坦,這里的putIndex會(huì)賦值0
//由此可見履植,items應(yīng)該是一個(gè)類似環(huán)形的數(shù)組。
if (++putIndex == items.length)
putIndex = 0;
count++;
//喚醒空隊(duì)列的take阻塞悄晃。
notEmpty.signal();
}
4玫霎、take方法(獲取數(shù)據(jù),隊(duì)列空則阻塞)
public E take() throws InterruptedException {
//由此可見传泊,put和take操作都是用的同一個(gè)鎖鼠渺。是互斥的
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
//如果隊(duì)列里沒有數(shù)據(jù),take方法阻塞
while (count == 0)
notEmpty.await();
//出隊(duì)操作
return dequeue();
} finally {
lock.unlock();
}
}
private E dequeue() {
final Object[] items = this.items;
//獲取takeIndex的元素
E x = (E) items[takeIndex];
//takeIndex位置設(shè)置為null
items[takeIndex] = null;
//與入隊(duì)操作相同眷细,++takeIndex后==items.length拦盹,則從頭繼續(xù)取元素
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
//更新迭代器中數(shù)據(jù)
itrs.elementDequeued();
//喚醒滿隊(duì)列的阻塞。
notFull.signal();
return x;
}
5溪椎、add方法(調(diào)用父類的add)普舆、offer方法
/**
* ArrayBlockingQueue 的add方法,向隊(duì)列添加元素
*/
public boolean add(E e) {
//調(diào)用父類add.
return super.add(e);
}
/**
* 父類AbstractQueue 的add方法校读,向隊(duì)列添加元素
* 隊(duì)列滿了就拋異常沼侣。
*/
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
/**
* ArrayBlockingQueue 的offer方法,向隊(duì)列添加元素
* 如果隊(duì)列滿了歉秫,就返回false蛾洛。不滿就入隊(duì)操作。返回true
*/
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();
}
}
6雁芙、offer(E e, long timeout, TimeUnit unit)方法
/**
* ArrayBlockingQueue 的offer方法轧膘,向隊(duì)列添加元素
* 如果隊(duì)列滿了,就阻塞兔甘,添加超時(shí)時(shí)間谎碍。
*/
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
checkNotNull(e);
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length) {
if (nanos <= 0)
return false;
nanos = notFull.awaitNanos(nanos);
}
enqueue(e);
return true;
} finally {
lock.unlock();
}
}
7、peek方法
/**
* 獲取當(dāng)前消費(fèi)指針(takeIndex)位置上的元素
* 但不移動(dòng)takeIndex指針洞焙,不清空當(dāng)前位置數(shù)據(jù)
*/
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return itemAt(takeIndex); // null when queue is empty
} finally {
lock.unlock();
}
}
final E itemAt(int i) {
return (E) items[i];
}