DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。我们可以将DelayQueue运用在以下应用场景:
- 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
- 定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。
具有过期时间的缓存
package test;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class SessionCache<K, V> {
public ConcurrentHashMap<K, V> map = new ConcurrentHashMap<K, V>();
public DelayQueue<DelayedItem<K>> queue = new DelayQueue<DelayedItem<K>>();
static class SingletonHolder {
static SessionCache instance = new SessionCache();
}
public static SessionCache getInstance() {
return SingletonHolder.instance;
}
public void put(K k, V v, long liveTime) {
V v2 = map.put(k, v);
DelayedItem<K> tmpItem = new DelayedItem<K>(k, liveTime);
if (v2 != null) {
queue.remove(tmpItem);
}
queue.put(tmpItem);
}
public SessionCache() {
Thread t = new Thread() {
@Override
public void run() {
dameonCheckOverdueKey();
}
};
t.setDaemon(true);
t.start();
}
public void dameonCheckOverdueKey() {
while (true) {
DelayedItem<K> delayedItem = queue.poll();
if (delayedItem != null) {
map.remove(delayedItem.getT());
System.out.println(System.nanoTime() + " remove " + delayedItem.getT() + " from cache");
}
try {
Thread.sleep(300);
} catch (Exception e) {
// TODO: handle exception
}
}
}
public static void main(String[] args) throws InterruptedException {
Random random = new Random();
int cacheNumber = 10;
Long liveTime = 200000000L;
SessionCache cache = SessionCache.getInstance();
for (int i = 0; i < cacheNumber; i++) {
liveTime = liveTime + random.nextInt(10) * 10000;
System.out.println(i + " " + liveTime);
cache.put(i + "", i + "", liveTime);
liveTime = 200000000L;
}
Thread.sleep(100000);
System.out.println();
}
}
class DelayedItem<T> implements Delayed {
private T t;
private long liveTime;
private long removeTime;
public DelayedItem(T t, long liveTime) {
this.setT(t);
this.liveTime = liveTime;
this.removeTime = TimeUnit.NANOSECONDS.convert(liveTime, TimeUnit.NANOSECONDS) + System.nanoTime();
}
@Override
public int compareTo(Delayed o) {
if (o == null)
return 1;
if (o == this)
return 0;
if (o instanceof DelayedItem) {
DelayedItem<T> tmpDelayedItem = (DelayedItem<T>) o;
if (liveTime > tmpDelayedItem.liveTime) {
return 1;
} else if (liveTime == tmpDelayedItem.liveTime) {
return 0;
} else {
return -1;
}
}
long diff = getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
return diff > 0 ? 1 : diff == 0 ? 0 : -1;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(removeTime - System.nanoTime(), unit);
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
@Override
public int hashCode() {
return t.hashCode();
}
@Override
public boolean equals(Object object) {
if (object instanceof DelayedItem) {
return object.hashCode() == hashCode() ? true : false;
}
return false;
}
}
参考: http://ifeve.com/java-blocking-queue/
已有 0 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐