特点
1、内部队列基于PriorityQueue,其要求放入的元素不能为null
2、放置在内的对象,只有满足条件:到期 且 排在队列出口的 才能取出
3、放置在内的对象必须实现Delayed接口,该接口有个getDelay方法,用于判断是否到达执行时间
示例代码
/**
* DelayQueue 可以延时取出的队列
* 注意:
* 内部元素必须实现接口: Delayed,要注意方法:compareTo、getDelay
*/
public class DelayQueueTest {
private static final Logger logger = Logger.getLogger(DelayQueueTest.class.getName());
private DelayQueue<Task> delayQueue = new DelayQueue<Task>();
public DelayQueueTest() {
}
class Task implements Delayed {
private String taskId;// 任务ID
private long excuteTime;// 延时多少毫秒执行
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public Task(String taskId, long excuteTime) {
this.excuteTime = System.currentTimeMillis() + excuteTime;
this.taskId = taskId;
}
// 因为:Delayed继承Comparable,所以必须实现的方法
// 注意:这个方法影响元素在队列内的顺序,所以,正常来说是要按照延时时间长短来判断,
// 延时短的要放在前面(方便出队),延时久的要放在后面
// 如果把延时时间短的放在了延时时间久的后面,那么即使时间到了,也无法取出,要等前面元素先出
public int compareTo(Delayed o) {
long result = this.getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
if (result > 0) {
return 1;
} else if (result < 0) {
return -1;
} else {
return 0;
}
}
// 返回是否已经到达出队时间
// <=0时间到达可以取出,否则未到无法取出
public long getDelay(TimeUnit unit) {
return unit.convert(excuteTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
}
private void test() {
// 放入延时队列
Task task1 = new Task("task1", 5000);// 5秒后取出
Task task2 = new Task("task2", 10000);
// 取出元素
delayQueue.put(task1);
logger.info("put " + task1.getTaskId() + " ok");
delayQueue.put(task2);
logger.info("put " + task2.getTaskId() + " ok");
Task tmpTask = null;
while (true) {
try {
tmpTask = delayQueue.take();
logger.info("take " + tmpTask.getTaskId() + " ok");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
DelayQueueTest dqt = new DelayQueueTest();
dqt.test();
}
}