基於DelayQueue帶有回調的超時緩存實現

    平時項目中總會用到超時緩存,並且希望超時之後會觸發一些後續處理邏輯,比如心跳。一般做法就是把這些數據放到一個隊列中,然後線程定時遍歷檢查是否超時。於是想自己實現一個簡單的可以自動超時的緩存隊列。在查了一些資料後發現DelayQueue是非常合適而且非常簡便的,網絡上基於DelayQueue實現超時緩存隊列的文章也很多,本文實現的超時隊列原理類似,支持多次檢查並增加了一些超時回調方法。


DelayQueue介紹


DelayQueue是BlockingQueue的一種,其內部的元素需要實現Delayed接口並實現getDelay方法。getDelay方法返回該元素距離失效還剩餘的時間,當<=0時元素就失效了,就可以從隊列中獲取到。正是利用DelayQueue的這個特性,定時取出DelayQueue中失效的元素,來實現超時緩存的功能。

功能演示


本文實現的超時緩存叫做ExpireCache,先看下ExpireCache的使用和特性
package ji.util;

import java.util.concurrent.TimeUnit;

/**
 * Created by ji on 17-6-22.
 */
public class ExpireCacheTest {

    public static void main(String[] args) throws InterruptedException {

        //創建一個ExpireCache,
        ExpireCache<String, String> expireCache = ExpireCache
                // 四個參數分別是:首次超時時間,超時繼續檢查時間間隔,時間單位,超時後是否連續檢查
                .setExpireTime(10, 2, TimeUnit.SECONDS, true)
                //超時多少次從隊列中移除,第四個參數爲true纔有效,爲false時第一次超時就會被刪掉
                .setCheckTimes(5)
                //註冊一個超時回調,元素超時後會觸發handler方法
                .build(new ExpireCallBack() {
                    @Override
                    public void handler(Object key, boolean isEnd) throws Exception {
                        System.out.println("元素:[" + key + "]超時,超時是否刪除:" + isEnd);
                    }
                });

        expireCache.put("key_a", "v_a");
        expireCache.put("key_b", "v_b");

        TimeUnit.SECONDS.sleep(2);

        //expire會重新計算超時時間
        expireCache.expire("key_a");

        TimeUnit.SECONDS.sleep(2);

        System.out.println(expireCache.get("key_a"));

        //put可以更新已存在的值,並重新計算超時時間
        expireCache.put("key_a", "v_a_new");

        System.out.println(expireCache.get("key_a"));

        Thread.sleep(100000000);
    }
}

使用說明


看一下創建一個ExpireCache的方法
ExpireCache<String, String> expireCache = ExpireCache
                // 四個參數分別是:首次超時時間,超時繼續檢查時間間隔,時間單位,超時後是否連續檢查
                .setExpireTime(10, 2, TimeUnit.SECONDS, true)
                //超時多少次從隊列中移除,第四個參數爲true纔有效,爲false時第一次超時就會被刪掉
                .setCheckTimes(5)
                //註冊一個超時回調,元素超時後會觸發handler方法
                .build(new ExpireCallBack() {
                    @Override
                    public void handler(Object key, boolean isEnd) throws Exception {
                        //回調方法邏輯
                    }
                });
  • setExpireTime(long firstExpireTime, long subsequentExpireTime, TimeUnit unit, boolean continueCheckAfterExpire)
    firstExpireTime : 超時時間
subsequentExpireTime : 下次檢查時間間隔,只有第四個參數爲true才生效
unit:時間單位
continueCheckAfterExpire: 超時後是否繼續檢查,false:失敗後直接從隊列中移除,true: 超時不移除,繼續檢查,和第二個參數配合
  • setCheckTimes(Integer times)
    設置共檢查多少次,當設置連續檢查爲true時才生效。當檢查到達該次數後會從隊列中移除。
  • build(ExpireCallBack<K, V> callBack) 
    創建的時候可以傳一個回調函數,每次元素失效檢查的時候都會觸發該回調方法。
  • build()
    當不需要回調的時候可以使用該方法創建。
  • put(K key, V value)
    添加元素,有則更新,同時會重新計算超時時間。
  • V get(K key)
    取元素
  • boolean containsKey(K key)
    判斷是否存在該元素
  • boolean expire(K key)
    更新超時時間,會重新計算超時。

源碼


這裏不對源碼做非常詳細的介紹,如果大家有疑問或者希望做詳細介紹,我後期再補充。這裏提供一下源碼地址,有興趣的同學可以看下:

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