本文是DelayQueue系列的上篇,主要聚焦延迟队列的基础概念和实现原理。通过循序渐进的讲解,带你深入理解DelayQueue的核心机制和内部实现。
博主匠心之作,强推专栏:
- JAVA集合专栏 【夜话集】
- JVM知识专栏
- 数据库sql理论与实战
- 小游戏开发
DelayQueue本质上是一个支持延时获取元素的无界阻塞队列,队列中的元素必须实现Delayed接口。在创建元素时可以指定多久才能从队列中获取当前元素,只有在延迟期满时才能从队列中提取元素。
DelayQueue的基本定义:
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E> {
// ...实现细节
}
DelayQueue的核心在于Delayed接口,所有放入队列的元素都必须实现这个接口。Delayed接口继承了Comparable接口,这意味着元素不仅要能计算剩余延迟时间,还需要支持排序功能,以便队列能够按照延迟时间的先后顺序进行排列。
Delayed接口定义:
public interface Delayed extends Comparable<Delayed> {
// 获取剩余延迟时间
long getDelay(TimeUnit unit);
}
getDelay方法返回的是剩余延迟时间,如果返回0或负数,则表示延迟已经到期,元素可以被取出。
下面通过一个简单的示例来展示DelayQueue的基本用法。首先,我们需要创建一个实现了Delayed接口的任务类:
public class DelayedTask implements Delayed {
private String taskName;
private long executeTime; // 任务执行时间
public DelayedTask(String taskName, long delayTime) {
this.taskName = taskName;
this.executeTime = System.currentTimeMillis() + delayTime;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return Long.compare(this.executeTime, ((DelayedTask) o).executeTime);
}
@Override
public String toString() {
return "DelayedTask{taskName='" + taskName + "', executeTime=" + executeTime + "}";
}
}
在这个DelayedTask类中:
接下来,我们使用DelayQueue来管理这些延时任务:
public class DelayQueueDemo {
public static void main(String[] args) throws InterruptedException {
// 创建延时队列
DelayQueue<DelayedTask> delayQueue = new DelayQueue<>();
// 添加延时任务
delayQueue.offer(new DelayedTask("任务1", 2000)); // 2秒后执行
delayQueue.offer(new DelayedTask("任务2", 1000)); // 1秒后执行
delayQueue.offer(new DelayedTask("任务3", 3000)); // 3秒后执行
// 获取任务执行
while (!delayQueue.isEmpty()) {
DelayedTask task = delayQueue.take(); // 按延时时间顺序获取任务
System.out.println("执行任务:" + task);
}
}
}
/* 运行结果:
执行任务:DelayedTask{taskName='任务2', executeTime=1703123456789}
执行任务:DelayedTask{taskName='任务1', executeTime=1703123457789}
执行任务:DelayedTask{taskName='任务3', executeTime=1703123458789}
*/
在这个示例中:
从运行结果可以看出,虽然任务1先添加,但任务2的延迟时间更短,所以任务2先被执行。这正是DelayQueue的核心特性:按照延迟到期时间排序,而不是按照添加顺序。
DelayQueue在实际项目中有很多应用场景,最典型的就是需要在一定时间后执行的任务。下面以订单超时自动取消为例,展示DelayQueue的实际应用:
订单超时自动取消示例:
public class OrderTimeoutExample {
private static final DelayQueue<DelayedOrder> ORDER_QUEUE = new DelayQueue<>();
public static void main(String[]