4.5.7 DelayQueue实现缓存设计

实体:

public class MyDelayed implements Delayed {
    private String key;
    private long currentTime;
    private long expireTime;

    public MyDelayed(String key, long expireTime) {
        this.key=key;
        this.expireTime=expireTime;
        this.currentTime = System.currentTimeMillis();
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    /**
     * 获取剩余的时间
     * @param unit
     * @return
     */
    @Override
    public long getDelay(TimeUnit unit) {
        return expireTime - unit.MILLISECONDS.toSeconds(System.currentTimeMillis()-currentTime);
    }

    /**
     * 剩余时间升序排列
     * @param o
     * @return
     */
    @Override
    public int compareTo(Delayed o) {
        MyDelayed p = (MyDelayed) o;
        if(this.getDelay(TimeUnit.MICROSECONDS) > p.getDelay(TimeUnit.MICROSECONDS))
            return 1;
        if(this.getDelay(TimeUnit.MICROSECONDS) > p.getDelay(TimeUnit.MICROSECONDS))
            return -1;
        return 0;
    }

    @Override
    public String toString() {
        return "MyDelayed{" +
                "key='" + key + '\'' +
                ", currentTime=" + currentTime +
                ", expireTime=" + expireTime +
                '}';
    }
}

缓存对象:还未过期的对象存储在map中

public class MyCache extends Thread {
    DelayQueue<MyDelayed> queue = new DelayQueue();
    //延迟队列只能保证延迟获取元素,但不会清楚时间归0的元素,所以使用map来作为中转
    ConcurrentHashMap<String, MyDelayed> map = new ConcurrentHashMap<>();

    public MyCache(){
        this.start();
    }
    //时刻检查队列中元素是不是到期
    @Override
    public void run() {
        while (true) {
            Iterator<MyDelayed> iterator = queue.iterator();
            while (iterator.hasNext()) {
                MyDelayed next = iterator.next();
                if (next.getDelay(TimeUnit.MICROSECONDS) <= 0) {
                    //System.out.println(next.getKey() + ":过期了--"+next.getDelay(TimeUnit.MICROSECONDS));
                    map.remove(next.getKey());
                }
            }
        }
    }

    public void add(String key, Long expireTime) {
        MyDelayed myDelayed = new MyDelayed(key, expireTime);
        queue.add(myDelayed);
        map.put(myDelayed.getKey(), myDelayed);
    }

    public Delayed get(String key) {
        return map.get(key);
    }


}

测试

public class Test extends Thread {


    public static void main(String[] args) throws InterruptedException {
        MyCache my = new MyCache();

        //每3秒给延时队列添加一个元素
        System.out.println("开始添加元素");
        Thread.sleep(1000);
        my.add("key-1", 1l);
        Thread.sleep(1000);
        my.add("key-2", 1l);

        //只要还没有过期,就能够从缓存中拿到数据
        while (true) {
            if (my.get("key-1") == null && my.get("key-2") == null) {
                System.out.println("key-1 过期了");
                System.out.println("key-2 过期了");
                break;
            }
            System.out.println("key-1 还没有过期:");
            System.out.println("key-2 还没有过期:");
        }
    }
}

结果

开始添加元素
key-1 还没有过期:
key-2 还没有过期:
。。。。。。
key-2 还没有过期:
key-1 过期了
key-2 过期了

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章