原文鏈接:http://cxis.me/2016/05/29/ArrayBlockingQueue%E7%AE%80%E4%BB%8B/
- 定義
- addE方法和offerE
- take方法
- 源碼分析
- ArrayBlockingQueueint capacity 給定容量和默認的訪問規則初始化
- ArrayBlockingQueueint capacity boolean fair知道你跟容量和訪問規則
- ArrayBlockingQueueint capacity boolean fairCollection
- addE e 添加元素到隊列末尾成功返回true隊列滿了拋異常IllegalStateException
- offerE e添加元素到隊列末尾成功返回true隊列滿了返回false
- putE e 添加元素到隊列末尾隊列滿了等待
- offerE e long timeout TimeUnit unit添加元素到隊列末尾如果隊列滿了等待指定的時間
- poll 移除隊列頭
- take 移除隊列頭隊列爲空的話就等待
- polllong timeout TimeUnit unit移除隊列頭隊列爲空等待指定的時間
- peek返回隊列頭不刪除
- size
- remainingCapacity 返回無阻塞情況下隊列能接受容量的大小
- removeObject o從隊列中刪除元素
- containsObject o 是否包含元素
- toArray
- toArrayT a
- toString
- clear
- drainToCollection
- drainToCollection
- iterator 返回一個迭代器
- 參考
- ArrayBlockingQueue基於數組,先進先出,從尾部插入到隊列,從頭部開始返回。
- 線程安全的有序阻塞隊列,內部通過“互斥鎖”保護競爭資源。
- 指定時間的阻塞讀寫
- 容量可限制
定義
ArrayBlockingQueue繼承AbstractQueue,實現了BlockingQueue,Serializable接口,內部元素使用Object[]數組保存。初始化時候需要指定容量ArrayBlockingQueue(int capacity)
,ArrayBlockingQueue默認會使用非公平鎖。
ArrayBlockingQueue只使用一把鎖,造成在存取兩種操作時會競爭同一把鎖,而使得性能相對低下。
add(E)方法和offer(E)
調用父類中的add方法,查看源碼可知父類中的add方法是調用offer方法實現,所以查看offer方法源碼,如下:
public boolean offer(E e) {
//檢查元素不爲null
checkNotNull(e);
//加鎖,獨佔鎖保護競態資源。
final ReentrantLock lock = this.lock;
lock.lock();
try {
//隊列已滿,返回false
if (count == items.length)
return false;
else {
//插入元素,返回true
insert(e);
return true;
}
} finally {
//釋放鎖
lock.unlock();
}
}
insert源碼如下:
private void insert(E x) {
//將元素添加到隊列中
items[putIndex] = x;
//putIndex表示下一個被添加元素的索引,設置下一個被添加元素的索引,若隊列滿了,就設置下一個被添加元素索引爲0
putIndex = inc(putIndex);
//隊列的元素數加1
++count;
//喚醒notEmpty上的等待線程,也就是取元素的線程。
notEmpty.signal();
}
take()方法
public E take() throws InterruptedException {
//獲取獨佔鎖,加鎖,線程是中斷狀態的話會拋異常
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
//隊列爲空,會一直等待
while (count == 0)
notEmpty.await();
//取元素的方法
return extract();
} finally {
//釋放鎖
lock.unlock();
}
}
private E extract() {
final Object[] items = this.items;
E x = this.<E>cast(items[takeIndex]);
//取完之後,刪除元素
items[takeIndex] = null;
//設置下一個被取出的元素索引,若是最後一個元素,下一個被取出的元素索引爲0
takeIndex = inc(takeIndex);
//元素數減1
--count;
//喚醒添加元素的線程
notFull.signal();
return x;
}
源碼分析
jdk1.7.0_71
//隊列元素
final Object[] items;
//下次被take,poll,remove的索引
int takeIndex;
//下次被put,offer,add的索引
int putIndex;
//隊列中元素的個數
int count;
//保護所有訪問的主鎖
final ReentrantLock lock;
//等待take鎖,讀線程條件
private final Condition notEmpty;
//等待put鎖,寫線程條件
private final Condition notFull;
ArrayBlockingQueue(int capacity) 給定容量和默認的訪問規則初始化
public ArrayBlockingQueue(int capacity){}
ArrayBlockingQueue(int capacity, boolean fair)知道你跟容量和訪問規則
//fair爲true,在插入和刪除時,線程的隊列訪問會阻塞,並且按照先進先出的順序,false,訪問順序是不確定的
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();
}
ArrayBlockingQueue(int capacity, boolean fair,Collection
public ArrayBlockingQueue(int capacity, boolean fair,
Collection<? extends E> c) {}
add(E e) 添加元素到隊列末尾,成功返回true,隊列滿了拋異常IllegalStateException
public boolean add(E e) {
return super.add(e);
}
offer(E e)添加元素到隊列末尾,成功返回true,隊列滿了返回false
public boolean offer(E e) {}
put(E e) 添加元素到隊列末尾,隊列滿了,等待.
public void put(E e) throws InterruptedException {}
offer(E e, long timeout, TimeUnit unit)添加元素到隊列末尾,如果隊列滿了,等待指定的時間
public boolean offer(E e, long timeout, TimeUnit unit){}
poll() 移除隊列頭
public E poll() {}
take() 移除隊列頭,隊列爲空的話就等待
public E take() throws InterruptedException {}
poll(long timeout, TimeUnit unit)移除隊列頭,隊列爲空,等待指定的時間
public E poll(long timeout, TimeUnit unit) throws InterruptedException {}
peek()返回隊列頭,不刪除
public E peek() {}
size()
public int size(){}
remainingCapacity() 返回無阻塞情況下隊列能接受容量的大小
public int remainingCapacity() {}
remove(Object o)從隊列中刪除元素
public boolean remove(Object o) {}
contains(Object o) 是否包含元素
public boolean contains(Object o) {}
toArray()
public Object[] toArray(){}
toArray(T[] a)
public <T> T[] toArray(T[] a) {}
toString()
public String toString(){}
clear()
public void clear(){}
drainTo(Collection
public int drainTo(Collection<? super E> c) {}
drainTo(Collection
public int drainTo(Collection<? super E> c, int maxElements) {}
iterator() 返回一個迭代器
public Iterator<E> iterator() {
return new Itr();
}