简介
DelayQueue是Java中的一个并发容器,它实现了Delayed接口,用于存储具有延迟时间的元素。DelayQueue内部使用PriorityQueue来存储元素,并根据元素的延迟时间进行排序。延迟时间指的是元素需要在指定的延迟时间之后才能被取出。
目前主流的延迟对应的方案为:使用mq的延迟队列。而DalayQueue是java自带的延迟队列,我们可以根据需求去选择。
使用
创建一个队列元素去实现 Delayed 接口。
import lombok.Data;
import java.time.Duration;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
@Data
public class DelayTask<D> implements Delayed {
//携带的数据
private D data;
//延迟时间
private long deadlineNanos;
public DelayTask(D data, Duration delayTime) {
this.data = data;
this.deadlineNanos = System.nanoTime() + delayTime.toNanos();
}
//元素在队列中的剩余时间
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(Math.max(0, deadlineNanos - System.nanoTime()), TimeUnit.NANOSECONDS);
}
//元素排序
@Override
public 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;
}
}
}
进行测试
import com.tianji.learning.utils.DelayTask;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.util.concurrent.DelayQueue;
@Slf4j
public class test1 {
@Test
public void consumeTask() throws InterruptedException {
//初始化延迟队列(初始化任务的数据为String类型)
DelayQueue<DelayTask<String>> delayTaskQueue = new DelayQueue<>();
//创建任务
log.info("加入任务!");
delayTaskQueue.add(new DelayTask<String>("延迟任务1", Duration.ofSeconds(1))); //1秒的延迟任务
delayTaskQueue.add(new DelayTask<String>("延迟任务2", Duration.ofSeconds(2))); //2秒的延迟任务
//设置监听器
while(!delayTaskQueue.isEmpty()) {
//poll不会进行阻塞,而take方法则会进行阻塞
DelayTask<String> take = delayTaskQueue.take();
log.info("执行任务: {}", take.getData());
}
}
}
DelayQueue.task方法不会阻塞(也就是在没有查到的时候,不会堵塞线程),而DelayQueue.poll方法则会进行阻塞。
总结
使用步骤
1.实现Delayed接口创建队列元素。
2.初始化延迟队列DelayQueue,并指定好对应的泛型。
3.创建任务,并添加到队列中。
4.创建监听器,在监听器获取到对应的数据后,执行后续的步骤。