實體:
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 過期了