DelayQueue实现Leader-Folloer pattern
1、当存在多个take线程时,同时只生效一个,即,leader线程
2、当leader存在时,其它的take线程均为follower,其等待是通过condition实现的
3、当leader不存在时,当前线程即成为leader,在delay之后,将leader角色释放还原
4、最后如果队列还有内容,且leader空缺,则调用一次condition的signal,唤醒挂起的take线程,其中之一将成为新的leader
5、最后在finally中释放锁
/**
* Retrieves and removes the head of this queue, waiting if necessary
* until an element with an expired delay is available on this queue.
*
* @return the head of this queue
* @throws InterruptedException {@inheritDoc}
*/
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null)
available.await(); /*队列为空则让当前线程在condition available上等待*/
else {
long delay = first.getDelay(TimeUnit.NANOSECONDS);
if (delay <= 0) /*超时时间已到,直接从队列中取出元素,线程返回。*/
return q.poll();
else if (leader != null) /*超时时间未到,且leader不为空(有线程正在处理),则当前调用线程在condition available上等待*/
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread; /*超时时间未到,且leader为空,则当前调用线程成为leader线程,leader是DelayQueue的private成员*/
try {
available.awaitNanos(delay); /*leader线程在condition available挂起直到超时时间满足,leader线程释放锁(atomically release the associated lock)*/
} finally { /*使用try finally保证finally中的语句务必执行*/
if (leader == thisThread) /*问题:finally是在线程唤醒,重新竞争到锁,然后从 awaitNanos 继续执行,最后执行到finally*/
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null) /*队列中有数据,且leader为空,则需要唤醒一下condition available等待队列上的线程,重新竞争锁,然后从挂起处继续执行*/
available.signal();
lock.unlock(); /*最后释放锁*/
}
}