1.queue常用方法:
remove:从队列中删除第一个元素,不存在报错。
poll:从队列中删除第一个元素,不存在返回null。
peek:查询第一个元素,不存在返回null。
add:往队列加一个元素,队列满报异常。
offer:往队列加一个元素,队列满返回false;
put: 往队列加一个元素,队列满时阻塞,直到队列有新的空间。
take:从队列中拿取第一个元素,队列为空则阻塞到队列有元素为止。
2.ArrayBlockingQueue源码:
2.1 add与offer:
public boolean add(E e) {
return super.add(e);
}
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
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();
}
}
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal(); //唤醒等待线程
}
2.2 put && take:
//put
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();//队列满,则等待
enqueue(e);
} finally {
lock.unlock();
}
}
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
//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() {
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal(); //拿出元素后,唤醒其他等待的线程
return x;
}
2.3 poll:
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : dequeue();
} finally {
lock.unlock();
}
}
3. PriorityBlockingQueue:
3.1 构造方法:
private static final int DEFAULT_INITIAL_CAPACITY = 11;
public PriorityBlockingQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
3.2 put、add、offer:
public void put(E e) {
offer(e); // never need to block
}
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
int n, cap;
Object[] array;
while ((n = size) >= (cap = (array = queue).length))
tryGrow(array, cap); //当队列满时,进行扩容
try {
Comparator<? super E> cmp = comparator;
if (cmp == null)
siftUpComparable(n, e, array); //排序
else
siftUpUsingComparator(n, e, array, cmp);
size = n + 1;
notEmpty.signal();
} finally {
lock.unlock();
}
return true;
}
4. SynchronousQueue :
4.1 构造方法:
public SynchronousQueue() {
this(false);
}
public SynchronousQueue(boolean fair) {
transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
if (transferer.transfer(e, false, 0) == null) {
Thread.interrupted();
throw new InterruptedException();
}
}
4.2 put or take:
根据e的元素是否为null判断
E transfer(E e, boolean timed, long nanos) {
SNode s = null; // constructed/reused as needed
int mode = (e == null) ? REQUEST : DATA;
for (;;) {
SNode h = head; //栈顶元素
if (h == null || h.mode == mode) { // empty or same-mode
//有超时且已到期
if (timed && nanos <= 0) { // can't wait
//头节点不为空且是取消状态
if (h != null && h.isCancelled())
//弹出头节点,并进入下一个循环
casHead(h, h.next); // pop cancelled node
else
return null;
} else if (casHead(h, s = snode(s, e, h, mode))) {//入栈成功
// 调用awaitFulfill()方法自旋+阻塞当前入栈的线程并等待被匹配到
SNode m = awaitFulfill(s, timed, nanos);
if (m == s) { // wait was cancelled
clean(s);
return null;
}
// 如果头节点不为空,并且头节点的下一个节点是s;把h和s都弹出
if ((h = head) != null && h.next == s)
casHead(h, s.next); // help s's fulfiller
// 根据当前节点的模式判断返回m还是s中的值
return (E) ((mode == REQUEST) ? m.item : s.item);
}
} else if (!isFulfilling(h.mode)) { // try to fulfill
if (h.isCancelled()) // 如果头节点已经取消了,就把它弹出栈
casHead(h, h.next);
else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
for (;;) { // loop until matched or waiters disappear
SNode m = s.next; // m is s's match 如果m为null,说明除了s节点外的节点都被其它线程先一步匹配掉了
if (m == null) { // all waiters are gone
casHead(s, null); // pop fulfill node
s = null; // use new node next time
break; // restart main loop
}
SNode mn = m.next;
if (m.tryMatch(s)) {
casHead(s, mn); // pop both s and m
return (E) ((mode == REQUEST) ? m.item : s.item);
} else // lost match
s.casNext(m, mn); // help unlink
}
}
} else { // help a fulfiller
SNode m = h.next; // m is h's match
if (m == null) // waiter is gone
casHead(h, null); // pop fulfilling node
else {
SNode mn = m.next;
if (m.tryMatch(h)) // help match
casHead(h, mn); // pop both h and m
else // lost match
h.casNext(m, mn); // help unlink
}
}
}
}
SNode awaitFulfill(SNode s, boolean timed, long nanos) {
// 到期时间
final long deadline = timed ? System.nanoTime() + nanos : 0L;
// 当前线程
Thread w = Thread.currentThread();
// 自旋次数
int spins = (shouldSpin(s) ?
(timed ? maxTimedSpins : maxUntimedSpins) : 0);
for (;;) {
if (w.isInterrupted())//当前线程中断,清除
s.tryCancel();
SNode m = s.match;
if (m != null)//匹配到了
return m;
if (timed) { //需要超时处理
nanos = deadline - System.nanoTime();
if (nanos <= 0L) {//超时
s.tryCancel();
continue;
}
}
if (spins > 0)//还有自旋次数
spins = shouldSpin(s) ? (spins-1) : 0;
else if (s.waiter == null)
s.waiter = w; // establish waiter so can park next iter
else if (!timed)
LockSupport.park(this);
else if (nanos > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanos);
}
}
4.3 注意:
1.两种创建模式,公平方式(队列),非公平方式(栈)(默认)。
2.栈的节点有三种模式:生产者,消费者,匹配中。
3.无缓存队列,用于两个线程直接移交元素,一般用于生产和消费相当的场景
5.DelayQueue:
5.1 put && take && peek:
///put
public void put(E e) {
offer(e);
}
public boolean offer(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
q.offer(e);
if (q.peek() == e) {
leader = null;
available.signal();
}
return true;
} finally {
lock.unlock();
}
}
//take
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek(); //查询第一个
if (first == null)
available.await(); //无元素,需要等待
else {
long delay = first.getDelay(NANOSECONDS); //等待时间
if (delay <= 0)
return q.poll(); //拿出元素
first = null; // don't retain ref while waiting将第一个置为null
if (leader != null)
available.await();//线程等待
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);//线程等待指定时间
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
//peek 查询,不等待,直接返回
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return q.peek();
} finally {
lock.unlock();
}
}
6 LinkedTransferQueue:
实现TransferQueue接口
6.1 put && take:
//put && take
public void put(E e) {
xfer(e, true, ASYNC, 0);
}
public E take() throws InterruptedException {
E e = xfer(null, false, SYNC, 0);
if (e != null)
return e;
Thread.interrupted();
throw new InterruptedException();
}
private E xfer(E e, boolean haveData, int how, long nanos) {
if (haveData && (e == null))//put请求且e为null
throw new NullPointerException();
Node s = null; // the node to append, if needed
retry:
for (;;) { // restart on append race
for (Node h = head, p = h; p != null;) { // find & match first node
boolean isData = p.isData;
Object item = p.item;
if (item != p && (item != null) == isData) { // unmatched
if (isData == haveData) // can't match 操作和节点类型不匹配,跳出内循环
break;
if (p.casItem(item, e)) { // match 操作和节点类型匹配
for (Node q = p; q != h;) {
Node n = q.next; // update by 2 unless singleton
if (head == h && casHead(h, n == null ? q : n)) {//设置新的head节点
h.forgetNext();//将旧的节点自连接,方便GC回收
break;跳出内循环
} // advance and retry
if ((h = head) == null ||
(q = h.next) == null || !q.isMatched())
break; // unless slack < 2
}
LockSupport.unpark(p.waiter);//匹配成功,唤醒阻塞线程
return LinkedTransferQueue.<E>cast(item);
}
}
//当前节点匹配完,寻找下一个节点
Node n = p.next;
p = (p != n) ? n : (h = head); // 当前节点已经离队,从head开始寻找
}
//整个队列都没匹配到
if (how != NOW) { // No matches available
if (s == null)
s = new Node(e, haveData);
//将s添加队尾,并返回s的前继节点
Node pred = tryAppend(s, haveData);
if (pred == null)//前继节点为Null,说明有线程竞争;则从retry开始
continue retry; // lost race vs opposite mode
if (how != ASYNC)//同步阻塞;;直到该节点被匹配或者取消
return awaitMatch(s, pred, e, (how == TIMED), nanos);
}
return e; // not waiting
}
}
6.2 注意:
LinkedTransferQueue实际上是一种预占模式:
消费线程获取元素,如果队列为空,则生成一个节点(节点元素为null)入队,消费者等待在这个节点上;
生产者线程发现有一个null的节点,它生产的元素不入队,直接填充到该节点上,并唤醒消费者去消费。若生产者找不到元素为null的节点,则直接入队。