DelayQueue的使用

一、背景

项目中经常会用到类似一些需要延迟执行的功能,比如缓存。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}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DelayQueue 是 Java 中的一个并发工具类,它实现了 Delayed 接口,可以用于存储元素并按照其过期时间进行排序。在多线程环境中,DelayQueue 可以用于实现延迟任务执行。当元素的过期时间到达时,可以从 DelayQueue 中取出该元素并执行相应的任务。 要使用 DelayQueue,首先需要创建 Delayed 接口的实现类,该类表示具有过期时间概念的元素。元素必须实现 getDelay 方法,该方法返回元素的剩余延迟时间。然后,将实现了 Delayed 接口的元素添加到 DelayQueue 中。 以下是一个简单的例子,演示了如何使用 DelayQueue: ```java import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; class DelayedElement implements Delayed { private String name; private long delayTime; public DelayedElement(String name, long delayTime) { this.name = name; this.delayTime = System.currentTimeMillis() + delayTime; } @Override public long getDelay(TimeUnit unit) { long diff = delayTime - System.currentTimeMillis(); return unit.convert(diff, TimeUnit.MILLISECONDS); } @Override public int compareTo(Delayed o) { return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS)); } @Override public String toString() { return name; } } public class DelayQueueExample { public static void main(String[] args) throws InterruptedException { DelayQueue<DelayedElement> delayQueue = new DelayQueue<>(); delayQueue.put(new DelayedElement("Element 1", 3000)); delayQueue.put(new DelayedElement("Element 2", 2000)); delayQueue.put(new DelayedElement("Element 3", 4000)); while (!delayQueue.isEmpty()) { DelayedElement element = delayQueue.take(); System.out.println("Processing: " + element); } } } ``` 在上面的例子中,我们创建了一个 DelayQueue,并向其中添加了三个元素。每个元素都有一个过期时间,分别为 3000 毫秒、2000 毫秒和 4000 毫秒。在主线程中,我们使用 take 方法从 DelayQueue 中获取元素并打印出来。 输出结果可能是: ``` Processing: Element 2 Processing: Element 1 Processing: Element 3 ``` 这是因为元素的过期时间不同,DelayQueue 会按照过期时间进行排序,先处理过期时间较小的元素。 希望这个例子能够帮助您理解 DelayQueue 的基本使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值