您好,欢迎访问一九零五行业门户网

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> { /** * 返回与此对象关联的剩余延迟(给定的时间单位)。 * @param unit 时间单位 * @返回剩余延迟;零值或负值表示 延迟已过期 */ 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() {}/** * 创建一个delayqueue,最初包含给定的collection实例集合。 * @param c 最初包含的元素集合 */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怎么使用的详细内容。
其它类似信息

推荐信息