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 過期了

 

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