線程安全的阻塞隊(duì)列,用來(lái)處理 生產(chǎn)者-消費(fèi)者 問(wèn)題。
當(dāng)隊(duì)列容器滿時(shí),生產(chǎn)者線程被阻塞直到隊(duì)列未滿。
當(dāng)隊(duì)列容器為空時(shí),消費(fèi)者線程阻塞直到隊(duì)列非空。
主要介紹BlockingQueue下三個(gè)實(shí)現(xiàn)類
1。ArrayBlockingQueue
底層使用數(shù)組來(lái)實(shí)現(xiàn)的有界阻塞隊(duì)列。
一旦構(gòu)造方法確定了數(shù)組容量大小后就不能改變,使用可重入鎖來(lái)控制,
構(gòu)造方法中可以選擇實(shí)現(xiàn)公平鎖還是非公平鎖。
公平鎖的意思是先等待的線程最先訪問(wèn)到ArrayBlockingQueue。
默認(rèn)是非公平鎖,因?yàn)楣芥i會(huì)降低隊(duì)列的吞吐性能。
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();
}
不管是插入操作還是讀取操作,都要獲取到鎖才能操作。
/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
2。LinkedBlockingQueue
底層使用單向鏈表實(shí)現(xiàn)的無(wú)界阻塞隊(duì)列。
默認(rèn)容量大小為Integer.MAX_VALUE
一般需要指定容量大小,不然會(huì)消耗大量?jī)?nèi)存。
指定容量大小可以當(dāng)做有界阻塞隊(duì)列來(lái)使用
不指定大小則當(dāng)做意義上的無(wú)界阻塞隊(duì)列。
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
3。PriorityBlockingQueue
一個(gè)支持優(yōu)先級(jí)的無(wú)界阻塞隊(duì)列
默認(rèn)情況下按照自然順序?qū)υ剡M(jìn)行排序
底層使用數(shù)組來(lái)實(shí)現(xiàn),默認(rèn)初始為11大小的數(shù)組,
后面隨著元素增加會(huì)不斷擴(kuò)容。
public PriorityBlockingQueue(int initialCapacity,
Comparator<? super E> comparator) {
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
this.comparator = comparator;
this.queue = new Object[initialCapacity];
}
添加元素時(shí)判斷是否當(dāng)前元素個(gè)數(shù)已經(jīng)大于數(shù)組容量了,就進(jìn)行擴(kuò)容
while ((n = size) >= (cap = (array = queue).length))
tryGrow(array, cap);
新的容量是看舊容量的多少來(lái)具體分配的,
舊容量越小增長(zhǎng)的快一點(diǎn)(增長(zhǎng)(oldCap + 2) ),
舊容量大一點(diǎn)的舊增長(zhǎng)的慢一點(diǎn)(增長(zhǎng)(oldCap >> 1))
int newCap = oldCap + ((oldCap < 64) ?
(oldCap + 2) : // grow faster if small
(oldCap >> 1));