【Java】DelayQueue
一,概述
本文简单介绍下延迟队列,顾名思义,加入队列的元素具备延时出队的特征,在诸如延迟消息时可简单使用,本文笔者以学习心态简单介绍下此数据结构。
DelayQueue实现类图如下
DelayQueue实现Queue接口,内部保存一个优先级队列,新加入队列的元素必须实现Delay接口,实现getDelay和compareTo方法,以满足优先级队列排序,以及出队延迟计算。
二,实例
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;public class DelayQueueMain {public static void main(String[] args) throws InterruptedException {DelayQueue<Message> queue = new DelayQueue<>();//创建一个消费者线程new Thread(() -> {try {System.out.println("Consumer Thread Create.");while (true) {Message message = queue.take();message.action.run();}} catch (InterruptedException e) {throw new RuntimeException(e);}}).start();//生产者for (int i = 0; i < 10; i++) {Message message = new Message((10 - i) * 200, i);queue.add(message);Thread.sleep(100);}}private static class Message implements Delayed {private final long createTime;private final long delayMs;private final long id;private final Runnable action = new Runnable() {@Overridepublic void run() {//简单demo,打印id即可System.out.println("invoke Message Id=" + id + ", DelayMs=" + delayMs);}};public Message(long delayMs, long id) {this.id = id;this.delayMs = delayMs;this.createTime = System.currentTimeMillis();}@Overridepublic long getDelay(TimeUnit unit) {return this.createTime + this.delayMs - System.currentTimeMillis();}@Overridepublic int compareTo(Delayed o) {long selfDelay = getDelay(TimeUnit.MILLISECONDS);long otherDelay = o.getDelay(TimeUnit.MILLISECONDS);if (selfDelay == otherDelay) {return 0;}return selfDelay > otherDelay ? 1 : -1;}}
}
输出如下
从上述结果可知,生产者加入队列的延迟消息,在消费者处如预期输出。
三,原理
优先级队列中,存放的元素实现了Delayed接口,通过getDelay可判断元素的优先级,delay小的优先在队列前端。
生产者offer
很简单,往队列中放一个元素,如果为空,则通过condition通知到消费者
消费者take
1,队列为空,通过condition等待
2,3,获得优先级队列第一个元素,并且计算当前getDelay值,小于0则出队,跳出for循环,否则继续超时await