一、背景
项目中经常会用到类似一些需要延迟执行的功能,比如缓存。java提供了DelayQueue来很轻松的实现这种功能。Delayed接口中的getDelay方法返回值小于等于0的时候,表示时间到达,可以从DelayQueue中通过take()方法取的到期的对象。到期对象是实现了Delayed的类。
二、代码实战
下面来模拟缓存失效的例子:
启动一个生产者线程,添加4个DelayedItem到DelayQueue队列。启动一个消费者线程从DelayQueue中获取已经到期的DelayedItem。为了看的比较明显一点,这里启动一个计数线程来模拟时钟。每个DelayedItem都有一个固定的失效时间removeTime,当getDelay方法返回值小于等于0的时候,表示有任务到达期限,这里用removeTime-count表示。从运行结果来看,当count值与removeTime值相等时,消费线程将会取得对象,若未到达期限,则消费线程一直阻塞。
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; public class DelayQueueTest { private static DelayQueue delayQueue = new DelayQueue(); private static long count = 0L; private static final int taskNum = 4; public static void main(String[] args) throws InterruptedException { Object num = new Object(); final DelayQueueTest delayQueueTest = new DelayQueueTest(); new Thread(new Runnable() { public void run() { try { delayQueueTest.producer(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); while(true) { if(delayQueue.size()==taskNum) { break; } } new Thread(new Runnable() { public void run() { try { delayQueueTest.consumer(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { public void run() { try { delayQueueTest.count(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } private void count() throws InterruptedException { while(true) { Thread.sleep(1000); count++; System.out.println("时间值="+count); if(taskNum==count) { break; } } } private void producer() throws InterruptedException { for(int i=0; i<taskNum; i++) { DelayedItem temp = new DelayedItem(i+"",i,(i+1)); System.out.println("生产者="+temp); delayQueue.put(temp); } } private void consumer() throws InterruptedException { while(true) { System.out.println("消费者="+delayQueue.take()); count = 0; } } static class DelayedItem<T> implements Delayed{ private String key; private T item; private long liveTime; private long removeTime; public DelayedItem(String key,T item,long liveTime) { this.key = key; this.item = item; this.liveTime = liveTime; this.removeTime = liveTime; } /** * 当返回值小于等于0时则缓存时间到达,take将取出元素 * @param unit * @return */ public long getDelay(TimeUnit unit) { return removeTime-count; } public int compareTo(Delayed o) { if(o instanceof DelayedItem) { //已经在队列中存在的对象 DelayedItem<T> tmpDelayedItem = (DelayedItem<T>)o; //System.out.println("比较对象==="+tmpDelayedItem.key+"==="+this.key); //失效时间越长的排到队尾 if(this.removeTime > tmpDelayedItem.removeTime) { return 1; } else if(this.removeTime == tmpDelayedItem.removeTime) { return 0; } else { return -1; } } return -1; } @Override public String toString() { return "DelayedItem{" + "key='" + key + '\'' + ", item=" + item + ", liveTime=" + liveTime + ", removeTime=" + removeTime + '}'; } } }
运行结果:
生产者=DelayedItem{key='0', item=0, liveTime=1, removeTime=1} 生产者=DelayedItem{key='1', item=1, liveTime=2, removeTime=2} 生产者=DelayedItem{key='2', item=2, liveTime=3, removeTime=3} 生产者=DelayedItem{key='3', item=3, liveTime=4, removeTime=4} 时间值=1 消费者=DelayedItem{key='0', item=0, liveTime=1, removeTime=1} 时间值=1 时间值=2 消费者=DelayedItem{key='1', item=1, liveTime=2, removeTime=2} 时间值=1 时间值=2 时间值=3 消费者=DelayedItem{key='2', item=2, liveTime=3, removeTime=3} 时间值=1 时间值=2 时间值=3 时间值=4 消费者=DelayedItem{key='3', item=3, liveTime=4, removeTime=4}