DelayQueue 延时队列,延时一段时间后执行的队列,根据这个特性,可以应用在
1 缓存的生成及自动过期删除
2 任务超时处理
…
其存储元素必须继承实现Delayed接口
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit unit);
}
可见 我们需要实现两个方法
1 getDelay 获取延迟时间
2 compareTo 内部队列的排序
我们先来看下 入队、出队
public boolean add(E e) {
return offer(e);
}
public void put(E e) {
offer(e);
}
public boolean offer(E e) {
// 两个作用
//1 下面的引用不需要通过this.lock,直接从堆栈获取引用 效率更高
//2 防止误操作
final ReentrantLock lock = this.lock;
//独占锁 线程安全
lock.lock();
try {
//这里的q是PriorityQueue 优先队列 fifo模式 可以看出DelayQueue 使用的是先进先出的模式,将对象放入队列中 这里会调用compareTo进行内部排序
q.offer(e);
//获取当前队列最顶队列对象,如果和当前对象相等,说明
//原先队列为空
if (q.peek() == e) {
leader = null;
//插入成功,通知唤醒
available.signal();
}
return true;
} finally {
// 释放锁
lock.unlock();
}
}
//排序方法
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
//循环比较,找到比自己大的 break
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
主要看的还是offer方法
//
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return q.peek();
} finally {
lock.unlock();
}
}
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
E first = q.peek();
//如果还未过期 则返回null
if (first == null || first.getDelay(NANOSECONDS) > 0)
return null;
else//
return q.poll();
} finally {
lock.unlock();
}
}
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);
//如果小于0,已经过时,直接抛出对象返回
if (delay <= 0)
return q.poll();
//对象回收
first = null; // don't retain ref while waiting
//如果当前leader已经被某线程赋值,则等待
if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
//否则赋值leader
leader = thisThread;
try {
//等待delay时间后 唤醒 继续循环
available.awaitNanos(delay);
} finally {
//leader=null
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
//当队列不为空,则进行通知,否则不通知
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
//he
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null) {
if (nanos <= 0)
return null;
else
nanos = available.awaitNanos(nanos);
} else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll();
if (nanos <= 0)
return null;
first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
long timeLeft = available.awaitNanos(delay);
nanos -= delay - timeLeft;
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
tack 方法貌似多点,不过整过过程还是比较简单的!
1 循环
2 判断是否过时
3 等待
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
//线程是否被打断 打断 则抛异常,这里和lock.lockInterruptibly();对应
if (Thread.interrupted())
throw new InterruptedException();
//通过当前线程 创建节点
Node node = addConditionWaiter();
//尝试是否,并且获取当前状态
int savedState = fullyRelease(node);
//过期时间
final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
//判断是否需要等待
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
//插到队列末尾
transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
//调用底层 对该线程进行阻塞
LockSupport.parkNanos(this, nanosTimeout);
//是否打断
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return deadline - System.nanoTime();
}
总结
适用于一段时间后执行的场景,常见于自定义缓存、超时、某段时间后需要处理的业务。