DelayQueue原理分析

转载 2015年07月10日 17:49:48

DelayQueue基本简介

DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的Delayed 元素。

DelayQueue是一个用来延时处理的队列,所谓延时处理就是说可以为队列中元素设定一个过期时间,相关的操作受到这个设定时间的控制。

DelayQueue使用场景

a) 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。
b) 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
c) 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求。

如果不使用DelayQueue,那么常规的解决办法就是:使用一个后台线程,遍历所有对象,挨个检查。这种笨笨的办法简单好用,但是对象数量过多时,可能存在性能问题,检查间隔时间不好设置,间隔时间过大,影响精确度,过小则存在效率问题。而且做不到按超时的时间顺序处理。

DelayQueue基本原理

首先,这种队列中只能存放实现Delayed接口的对象,而此接口有两个需要实现的方法。最重要的就是getDelay,这个方法需要返回对象过期前的时间。简单说,队列在某些方法处理前,会调用此方法来判断对象有没有超时。

其次,DelayQueue是一个BlockingQueue,其特化的参数是Delayed。(不了解BlockingQueue的同学,先去了解BlockingQueue再看本文)
Delayed扩展了Comparable接口,比较的基准为延时的时间值,Delayed接口的实现类getDelay的返回值应为固定值(final)。DelayQueue内部是使用PriorityQueue实现的。

总结,DelayQueue的关键元素BlockingQueue、PriorityQueue、Delayed。可以这么说,DelayQueue是一个使用优先队列(PriorityQueue)实现的BlockingQueue,优先队列的比较基准值是时间。本质上即:

DelayQueue = BlockingQueue +PriorityQueue + Delayed


他们的基本定义如下

public interface Comparable<T> {
    
public int compareTo(T o);
}

public interface Delayed extends Comparable<Delayed> {
    
long getDelay(TimeUnit unit);
}

public class DelayQueue<extends Delayed> implements BlockingQueue<E> { 
    
private final PriorityQueue<E> q = new PriorityQueue<E>();
}

DelayQueue内部的实现使用了一个优先队列。当调用DelayQueue的offer方法时,把Delayed对象加入到优先队列q中。如下:
public boolean offer(E e) {
    
final ReentrantLock lock = this.lock;
    lock.lock();
    
try {
        E first 
= q.peek();
        q.offer(e);
        
if (first == null || e.compareTo(first) < 0)
            available.signalAll();
        
return true;
    } 
finally {
        lock.unlock();
    }
}

DelayQueue的take方法,把优先队列q的first拿出来(peek),如果没有达到延时阀值,则进行await处理。如下:
public E take() throws InterruptedException {
    
final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    
try {
        
for (;;) {
            E first 
= q.peek();
            
if (first == null) {
                available.await();
            } 
else {
                
long delay =  first.getDelay(TimeUnit.NANOSECONDS);
                
if (delay > 0) {
                    
long tl = available.awaitNanos(delay);
                } 
else {
                    E x 
= q.poll();
                    
assert x != null;
                    
if (q.size() != 0)
                        available.signalAll(); 
// wake up other takers
                    return x;

                }
            }
        }
    } 
finally {
        lock.unlock();
    }
}

-------------------

DelayQueue 队列

DelayQueue----一种有序队列,特点就是只有在队列中的元素到期后才能取出。               1.内存中哪些对象到了超时时间,需要从内存中清除出去。            ...
  • yjl49
  • yjl49
  • 2011年12月20日 17:14
  • 3850

DelayQueue 学习

DelayQueue 学习介绍jdk里面的解释是:* An unbounded {@linkplain BlockingQueue blocking queue} of * {@code Delay...

delayQueue原理理解之源码解析

http://www.jianshu.com/p/e0bcc9eae0ae 内部结构 可重入锁 用于根据delay时间排序的优先级队列 用于优化阻塞通知的线程元素leader 用于实现阻塞...
  • bluetjs
  • bluetjs
  • 2016年11月01日 20:21
  • 967

队列queue的详细讲解

 一、Java  Queue基础 Queue: 基本上,一个队列就是一个先入先出(FIFO)的数据结构 offer,add区别: 一些队列有大小限制,因此如果想在一个满的队列中加入一个新项...
  • hui12581
  • hui12581
  • 2015年04月13日 11:10
  • 15707

DelayQueue 源码分析

http://afredlyj.github.io/posts/delayqueue.html DelayQueue是一个无界的阻塞队列,从这个队列中取出来的元素都是过期的,head头是过期...
  • bluetjs
  • bluetjs
  • 2016年11月01日 20:20
  • 645

使用delayedQueue实现你本地的延迟队列

了解DelayQueue DelayQueue是什么 DelayQueue能做什么 怎么用DelayQueue来解决这类的问题 先声明一个Delayed的对象 再实现一个管理延迟任务的类 使用方法 了...

DelayedQueue

DelayedQueue是一个用来延时处理的队列, * 所谓延时处理就是说可以为队列中元素设定一个过期时间, * 相关的操作受到这个设定时间的控制。 首先,这种队列中只能存放实现De...

DelayQueue延时队列的使用

在谈到DelayQueue的使用和原理的时候,我们首先介绍一下DelayQueue,DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的De...

延迟队列DelayQueue

应用场景:消息延迟60秒发送,如果用调度去查询执行的话,会有误差public class Test2 { public static void main(String[] args) thro...

使用Java的DelayQueue容易碰到的一个坑

先看一下整个code吧: import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import jav...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DelayQueue原理分析
举报原因:
原因补充:

(最多只允许输入30个字)