package com.test.t1;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
* DelayedQueue是一个用来延时处理的队列,
* 所谓延时处理就是说可以为队列中元素设定一个过期时间,
* 相关的操作受到这个设定时间的控制。
首先,这种队列中只能存放实现Delayed接口的对象,
而此接口有两个需要实现的方法。最重要的就是getDelay,
这个方法需要返回对象过期前的countdown时间。
简单说,队列在某些方法处理前,会调用此方法来判断对象有没有超时。
DelayedQueue本身有些类似的存取方法,按doc描述区别如下:
存入队列:add offer put无太大区别
从队列中获取:peek poll take有较大不同使用场景
peek:获取队列的head对象,但不是从队列中移除。如果队列空,就返回空
poll :获取并移出队列head对象。如果head没有超时,返回空
poll w/ timeout参数 : 获取并移出队列head对象。如果没有超时head对象,会wait当前线程知道有超时对象,或者按照超时参数设定,返回空
take : 获取并移出队列head对象。如果没有超时head对象,会wait当前线程知道有对象满足超时条件
DelayedQueue实现保证了最快过期的对象排在head位置,也就是说它会在每次peek时候返回最快超时的对象。
* @author lulei
*
*/
public class DelayedElement implements Delayed {
private final long delay;
private final long expire;
public DelayedElement(long delay) {
this.delay = delay;
expire = Calendar.getInstance().getTimeInMillis() + delay;
}
@Override
public long getDelay(TimeUnit unit) {
return expire - Calendar.getInstance().getTimeInMillis();
}
@Override
public int compareTo(Delayed o) {
return (int) (this.delay - o.getDelay(TimeUnit.MILLISECONDS));
}
@Override
public String toString() {
SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return "DelayedElement is " + delay + "
" +
sf.format(Calendar.getInstance().getTime()) + "
过期时间是"
+ getDelay(TimeUnit.DAYS);
}
/**
* 测试方法
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
System.out.println("测试延迟队列");
@SuppressWarnings("rawtypes")
DelayQueue delayQueue = new DelayQueue();
DelayedElement el1 = new DelayedElement(5000);
DelayedElement el2 = new DelayedElement(3000);
delayQueue.offer(el1);
delayQueue.offer(el2);
Delayed poll = null;
while (poll == null) {
poll = delayQueue.poll();
System.out.println("poll 的结果
" + poll);
System.out.println("poll 的结果
" + delayQueue.peek());
Thread.sleep(500);
}
}
}