延迟队列的入门使用
思考:
1.什么是延迟队列?延迟队列运用场景?
2.延迟队列的排队过程如何实现?真的是先进先出吗?
3.如何实现运用延迟队列
一.什么是延迟队列
DelayQueue 是Java 中的一个基于优先级队列的实现的线程安全的延迟队列。
运用场景:实现定时任务或者延迟任务的调度。
DelayQueue实现BlockingQueue,加入这个队列的元素必须实现Delayed接口,当生产者提交元素进入队列时,会重发Delayed接口中的compareTo方法进行比较排序,这样就使得队列的元素是按延迟时间进行排序的。
消费者线程查看队列头部的元素,是查看不是取出。然后调用元素的getDelay方法,如果此方法返回的值小0或者等于0,则消费者线程会从队列中取出此元素,并进行处理。如果getDelay方法返回的值大于0,则消费者线程wait返回的时间值后,再从队列头部取出元素,此时元素应该已经到期。
开发场景使用:
- 网民淘宝下订单:下单之后如果三十分钟之内没有付款就自动取消订单。
- 饿了吗订餐通知:下单成功后60s之后给用户发送短信通知。
- 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
延迟队列的demo
DelayQueue 的主要方法包括:
- add(E e) 和 offer(E e): 向队列中添加一个元素。
- take(): 从队列中取出一个元素,如果队列为空,则阻塞等待直到有元素可取。
- poll(): 从队列中取出一个元素,如果队列为空,则返回 null。
- size(): 返回队列中元素的数量。
package com.dqw.delayQueue;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import lombok.Data;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class DelayTask implements Delayed {
private String name;
private long delayTime;
public DelayTask(String name, long delayTime) {
this.name = name;
this.delayTime = System.currentTimeMillis()+delayTime;
}
@Override
public long getDelay(TimeUnit unit) {
long diff=delayTime-System.currentTimeMillis();
return unit.convert(diff,TimeUnit.MILLISECONDS) ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getDelayTime() {
return delayTime;
}
public void setDelayTime(long delayTime) {
this.delayTime = delayTime;
}
@Override
public int compareTo(Delayed o) {
return Long.compare(this.delayTime, ((DelayTask) o).delayTime);
}
}
@Test
void contextLoads() throws InterruptedException {
DelayQueue<DelayTask> delayQueue = new DelayQueue<>();
// 添加延时任务
delayQueue.add(new DelayTask("Task 1", 2000));
delayQueue.add(new DelayTask("Task 2", 4000));
delayQueue.add(new DelayTask("Task 3", 6000));
// 取出延时任务并执行
while (!delayQueue.isEmpty()) {
DelayTask task = delayQueue.take();
System.out.println("Executing task: " + task.getName());
}
}