DelayQueue 是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue 来实现。队列中的元素必须实现Delayed 接口,在创建元素时可以指定多久才能从队列中获取当前元素。 只有在延迟期满时才能从队列中提取元素。
DelayQueue 非常有用,可以将 DelayQueue 运用在以下应用场景。
- 缓存系统的设计:可以用 DelayQueue 保存缓存元素的有效期,使用一个线程循环查询 DelayQueue,一旦能从DelayQueue 中获取元素时,表示缓存有效期到了。
- 定时任务调度:使用 DelayQueue 保存当天将会执行的任务和执行时间,一旦从 DelayQueue 中获取到任务就开始执行,比如 TimerQueue 就是使用 DelayQueue 实现的。
1.实现 Delay 接口
public interface Delayed extends Comparable<Delayed> {
/**
* Returns the remaining delay associated with this object, in the
* given time unit.
*
* @param unit the time unit
* @return the remaining delay; zero or negative values indicate
* that the delay has already elapsed
*/
long getDelay(TimeUnit unit);
}
需要实现两个方法:
- comparTo(Delayed o):让延时时间最长的放在队列的末尾(即最早可以获取的元素放在队首)。
- getDelay(TimeUnit unit):返回剩余延迟时间,返回负数则说明已经过了延迟时间,可以获取元素。
2.延迟队列原理
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