概念
DelayQueue是BlockingQueue的实现类,在原本的基础上增加了延迟等待的操作,底层用到了PriorityQueue和Leader-Follower模式。
Delayed
DelayQueue中存储的对象必须是Delayed,赋予了延迟操作的能力,Delayed继承Comparable,因此也要重写compareTo方法
public interface Delayed extends Comparable<Delayed> {
/**
*
*
* @param unit 时间单位
* @return 返回等待的时间
*/
long getDelay(TimeUnit unit);
}
put方法
public void put(E e) {
offer(e);
}
private final PriorityQueue<E> q = new PriorityQueue<E>(); //优先级队列,按照延迟最小排序
public boolean offer(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
q.offer(e);
if (q.peek() == e) { //如果新加入的是最小的延迟时间,就重新唤醒一个作为leader去处理
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) //为null就等待
available.await();
else {
//不为null就获取延迟时间
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0) //延迟时间<=0 就poll
return q.poll();
first = null;
if (leader != null) //已经存在leader就等待即可
available.await();
else {
//不存在leader,就用当前线程作为leader
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();
}
}
总结
DelayQueue使用PriorityQueue进行延迟时间排序,当不存在leader时,会使用当前线程作为leader,如果存在,判断时间是否新加入的时间更少,如果是就唤醒一个新的follower成为leader去处理。