Java DelayQueue(转)

DelayQueueBlockingQueue的一个实现.它没有容量大小限制.

DelayQueue中的元素,必须实现java.util.concurrent.Delayed接口.实现了它之后,所有放进DelayQueue中的元素,都会在一段时间之后才可用.

其中java.util.concurrent.Delayed接口,又implements了Comparable接口.所以我们需要同时实现Comparable接口的compareTo方法以及Delayed接口的getDelay方法.

DelayQueue会将过期时间最短的元素,放到队首,这就是通过**Comparable **接口来实现的.

DelayQueue的使用场景也很广泛,比如缓存系统的设计,以及定时任务调度等.

package com.projecthome;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
 * Created by yangyu on 16/11/27.
 */

/**
 * DelayQueue是一个支持延时获取元素的无界队列
 * DelayQueue可以用于如下场景:
 * 1.缓存系统的的设计:用DelayQueue保存缓存元素的有效期,用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取到元素,说明该元素过期了
 * 2.定时任务调度:使用DelayQueue保存当天会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,TimerQueue就是使用DelayQueue实现的
 * DelayQueue的原理:
 * 1.当线程put元素的时候,DelayQueue会对你put的元素通过其本身的compareTo方法进行排序,延时时间越短的顺序越靠近队列头部
 * 2.当线程take元素的时候,DelayQueue会检测当前是否有Thread已经在等待队头元素了,如果有的话,那么只能阻塞当前前程,等已经取到队头
 * 的Thread完成以后再唤醒。
 * 如果没有Thread在等待队头元素的话,那么会查询一下队头元素还剩多少Delay时间,并且将当前线程设置为队头等待线程,然后让当前线程wait剩余
 * Delay时间后在来获取队头元素。
 */
public class TestDelayQueue {
    public static void main(String[] args) {
        DelayQueue<Message> delayQueue = new DelayQueue<>();
        delayQueue.put(new Message(100000,"yangyu"));
        delayQueue.put(new Message(1000, "hello"));
        delayQueue.put(new Message(10000, "world"));

        try {
            while (delayQueue.isEmpty() == false) {
                System.out.println(delayQueue.take());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("end");
    }

    private static class Message implements Delayed{

        private long nanoTime;

        private String data;

        Message(long millisTime ,String data){
            this.nanoTime = now()+millisTime*(1000*1000);
            this.data = data;
        }

        private final long now(){
            return System.nanoTime();
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(nanoTime - now(), NANOSECONDS);
        }

        @Override
        public int compareTo(Delayed other) {
            if (other == this) // compare zero if same object
                return 0;
            if (other instanceof Message) {
                Message x = (Message) other;
                long diff = nanoTime - x.nanoTime;
                if (diff < 0)
                    return -1;
                else if (diff > 0)
                    return 1;
                else
                    return 1;
            }
            long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
            return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
        }
    }
}

原文链接:http://www.szeju.com/index.php/java/3526912.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home...
    光剑书架上的书阅读 4,206评论 2 8
  • 译序 本指南根据 Jakob Jenkov 最新博客翻译,请随时关注博客更新:http://tutorials.j...
    高广超阅读 5,498评论 1 68
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 35,094评论 18 399
  • 又是熟悉的电话铃声响起,看着上面的号码,不情愿的从床上起来,嘴里嘟囔着“又有什么事呀,非要这个时候打电话!“,不情...
    你是不一样的烟火阅读 366评论 0 0
  • 大约是两年前第一次听说GO语言,断断续续地看教程,没有进行系统的学习,在平时也没有真正用上,所以仍旧停留在小白水平...
    ww4u阅读 388评论 0 0

友情链接更多精彩内容