DelayQueue延迟队列的使用
1、DelayQueue简介
DelayQueue 也是 Java 并发包(java.util.concurrent)中的一个特殊队列,用于在指定的延迟时间之后处理元素。
DelayQueue的一些关键特性:
延迟元素处理:只有当元素的延迟时间到期时,元素才能被取出。使用 take 方法会阻塞直到有元素到期。
无界队列:DelayQueue 是一个无界队列,这意味着它可以包含任意数量的元素(太多可能内存溢出)。
元素排序:DelayQueue 中的元素按到期时间排序,最先到期的元素最早被取出。
阻塞操作:take 方法会阻塞直到有元素到期,而 poll 方法可以在指定的时间内等待。
2、DelayQueue适用场景
DelayQueue 通常用于需要在未来某个时间点执行任务的场景。
定时任务调度:可以用于实现定时任务调度系统,任务在特定的时间点被执行。
缓存过期:实现缓存系统中的过期机制,当缓存项的过期时间到达时,将其从缓存中移除。
限流控制:在某些系统中用于限流,限制某一操作在指定时间段内的执行频率。
3.DelayQueue 常见使用场景示例
我们这里希望任务可以按照我们预期的时间执行,例如提交 3 个任务,分别要求 1s、2s、3s 后执行,即使是乱序添加,1s 后要求 1s 执行的任务会准时执行。
对此我们可以使用 DelayQueue 来实现,所以我们首先需要继承 Delayed 实现 DelayedTask,实现 getDelay 方法以及优先级比较 compareTo。
import lombok.Data;import java.time.Duration;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;/*** 延迟任务*/
@Data
public class DelayedTask<D> implements Delayed {/*** 任务到期时间*/private long deadlineNanos;/*** 待处理数据*/private D data;public DelayedTask(Duration delayTime, D data) {this.deadlineNanos = System.nanoTime() + delayTime.toNanos();this.data = data;}/*** 查看当前任务还有多久到期** @param unit 时间单位* @return 到期时间*/@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(Math.max(0, deadlineNanos - System.nanoTime()), TimeUnit.NANOSECONDS);}/*** 延迟队列需要到期时间升序入队,所以我们需要实现compareTo进行到期时间比较** @param o 延迟任务* @return 比较大小*/@Overridepublic int compareTo(Delayed o) {long l = getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);if (l > 0) {return 1;} else if (l < 0) {return -1;} else {return 0;}}/*** 输出数据*/public void execute() {System.out.println(data);}}
使用:
// 创建延迟队列,并添加任务
DelayQueue<DelayedTask<String>> delayQueue = new DelayQueue<>();
//分别添加1s、2s、3s到期的任务
delayQueue.add(new DelayedTask<>(Duration.ofSeconds(2), "Task 2"));
delayQueue.add(new DelayedTask<>(Duration.ofSeconds(1), "Task 1"));
delayQueue.add(new DelayedTask<>(Duration.ofSeconds(3), "Task 3"));
// 取出任务并执行
while (!delayQueue.isEmpty()) {//阻塞获取最先到期的任务DelayedTask<String> task = delayQueue.take();task.execute();
}
4.DelayQueue的源码解析
见《DelayQueue详解-CSDN博客》