Java线程池队列中的延迟队列DelayQueue怎么使用
今天小编给大家分享一下Java线程池队列中的延迟队列DelayQueue怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
在阻塞队里中,除了对元素进行增加和删除外,我们可以把元素的删除做一个延迟的处理,即使用DelayQueue的方法。本文就来和大家聊聊Java线程池队列中的DelayQueue—延迟队列
public enum QueueTypeEnum { ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQueue"), LINKED_BLOCKING_QUEUE(2, "LinkedBlockingQueue"), DELAY_QUEUE(3, "DelayQueue"), PRIORITY_BLOCKING_QUEUE(4, "PriorityBlockingQueue"), SYNCHRONOUS_QUEUE(5, "SynchronousQueue"), LINKED_TRANSFER_QUEUE(6, "LinkedTransferQueue"), LINKED_BLOCKING_DEQUE(7, "LinkedBlockingDeque"), VARIABLE_LINKED_BLOCKING_QUEUE(8, "VariableLinkedBlockingQueue"), MEMORY_SAFE_LINKED_BLOCKING_QUEUE(9, "MemorySafeLinkedBlockingQueue");}
DelayQueue延迟队列
类似于PriorityBlockingQueue,是二叉堆实现的无界优先级阻塞队列。要求元素都实现Delayed 接口,通过执行时延从队列中提取任务,只有在延迟期满后才能从中提取元素。DelayQueue的泛型参数需要实现Delayed接口,Delayed接口继承了Comparable接口,DelayQueue内部使用非线程安全的优先队列(PriorityQueue),并使用Leader/Followers模式,最小化不必要的等待时间。DelayQueue不允许包含null元素。
public interface Delayed extends Comparable<Delayed> { long getDelay(TimeUnit unit);}
DelayQueue使用场景
缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
定时任务调度:使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。
DelayQueue属性
//可重入同步锁private final transient ReentrantLock lock = new ReentrantLock();//DelayQueue的实现依赖于PriorityQueue(优先队列)private final PriorityQueue<E> q = new PriorityQueue<E>();//第一个等待某个延时对象的线程,在延时对象还没有到期时其他线程看到这个leader不为null,那么就直接wait//主要是为了避免大量线程在同一时间点唤醒,导致大量的竞争,反而影响性能private Thread leader = null;//条件队列,用于wait线程private final Condition available = lock.newCondition();
DelayQueue构造方法
//从上面属性就可以看出,DelayQueue采用了饿汉模式,调用构造方法即创建了队列实例public DelayQueue() {}public DelayQueue(Collection<? extends E> c) { this.addAll(c);}
实现Delayed接口使用示例
class MyDelay<T> implements Delayed { long delayTime; // 延迟时间 long expire; // 过期时间 T data; public MyDelay(long delayTime, T t) { this.delayTime = delayTime; // 过期时间 = 当前时间 + 延迟时间 this.expire = System.currentTimeMillis() + delayTime; data = t; } @Override public long getDelay(TimeUnit unit) { return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public int compareTo(Delayed o) { long f = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS); return (int) f; } @Override public String toString() { return "delayTime=" + delayTime + ", expire=" + expire + ", data=" + data; }}public class DelayQueueDemo { static BlockingQueue<Delayed> queue = new DelayQueue(); public static void main(String[] args) throws InterruptedException { queue.add(new MyDelay(8, "第一次添加任务")); queue.add(new MyDelay(3, "第二次添加任务")); queue.add(new MyDelay(5, "第三次添加任务")); while (!queue.isEmpty()) { Delayed delayed = queue.take(); System.out.println(delayed); } }}
DelayQueue总结
DelayQueue其实采用了装饰器模式,在对PriorityQueue进行包装下增加了延时时间获取元素的功能,其主要特点归纳如下:
DelayQueue是一个无界阻塞队列,队列内部使用PriorityQueue来实现
进入队列的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素,只有在延迟期满时才能从中提取元素
该队列头部是延迟期满后保存时间最长的Delayed元素
如果没有延迟未过期元素,且队列没有头部,并且poll将返回null
当一个元素的getDelay(TimeUnit.NANOSECONDS)方法返回一个小于等于0的值时,表示该元素已过期
无法使用poll或take移除未到期的元素,也不会将这些元素作为正常元素对待;例如:size方法返回到期和未到期元素的计数之和
此队列不允许使用null元素
以上就是“Java线程池队列中的延迟队列DelayQueue怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341