欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java延迟队列

程序员文章站 2024-03-18 11:22:40
...

Java延迟队列

延迟队列分为两点:第一他是个队列,所以具有对列功能。第二就是延时,这就是延时对列。功能就是将任务放在该延时对列中,只有到了延时时间才能从该延时对列中获取任务否则获取不到!!!

应用场景比较多,比如延时1分钟发短信,延时1分钟再次执行等,下面先看看延时队列demo之后再看延时队列在项目中的使用。

首先,我们来看看基于内存的队列。在Java的并发包中已经提供了BlockingQueue的实现,比较常用的有ArrayBlockingQueue和LinkedBlockingQueue,前者是以数组的形式存储,后者是以Node节点的链表形式存储。至于数组和链表的区别这里就不多说了。

BlockingQueue 队列常用的操作方法:

  • 往队列中添加元素: add(), put(), offer()

  • 从队列中取出或者删除元素: remove() element() peek() pool() take()

每个方法的说明如下:

  • offer()方法往队列添加元素如果队列已满直接返回false,队列未满则直接插入并返回true

  • add()方法是对offer()方法的简单封装.如果队列已满,抛出异常new IllegalStateException(“Queue full”)

  • put()方法往队列里插入元素,如果队列已经满,则会一直等待直到队列为空插入新元素,或者线程被中断抛出异常

  • remove()方法直接删除队头的元素

  • peek()方法直接取出队头的元素,并不删除

  • element()方法对peek方法进行简单封装,如果队头元素存在则取出并不删除,如果不存在抛出异常NoSuchElementException()

  • pool()方法取出并删除队头的元素,当队列为空,返回null

  • take()方法取出并删除队头的元素,当队列为空,则会一直等待直到队列有新元素可以取出,或者线程被中断抛出异常

offer()方法一般跟pool()方法相对应, put()方法一般跟take()方法相对应.日常开发过程中offer()与pool()方法用的相对比较频繁.


示例


package com.monkey.delayqueue;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @Author: LailaiMonkey
 * @Description:
 * @Date:Created in 2020-02-09 14:40
 * @Modified By:
 */
public class Test {


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

        DelayQueue<DelayedModel> delayQueue = new DelayQueue<>();

        DelayedModel delayedModel = new DelayedModel("1", "这是第一条消息", 5000);
        delayQueue.put(delayedModel);

        DelayedModel delayedModel2 = new DelayedModel("2", "这是第二条消息", 10000);
        delayQueue.put(delayedModel2);

        DelayedModel delayedModel3 = new DelayedModel("3", "这是第三条消息", 13000);
        delayQueue.put(delayedModel3);

        while (true) {
            if (delayQueue.isEmpty()) {
                break;
            }
            DelayedModel take = delayQueue.take();
            System.out.println("出队消息的id:" + take.getId() + ",这是消息内容:" + take.getMag());
        }
    }

    static class DelayedModel implements Delayed {

        /**
         * 消息Id
         */
        private String id;

        /**
         * 消息内容
         */
        private String mag;

        /**
         * 过期时间
         */
        private long expire;

        DelayedModel(String id, String mag, long expire) {
            this.id = id;
            this.mag = mag;
            //到期时间 = 当前时间+延迟时间
            this.expire = System.currentTimeMillis() + expire;
        }

        // 延迟任务是否到时就是按照这个方法判断如果返回的是负数则说明到期否则还没到期
        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        // 如果实现比较器将根据比较器返回结果获得队列元素

        @Override
        public int compareTo(Delayed delayed) {
            // 根据过期时间升序出队
            int compare = Math.toIntExact((this.getDelay(TimeUnit.MILLISECONDS) - delayed.getDelay(TimeUnit.MILLISECONDS)));
            return compare;
        }

//        @Override
//        public int compareTo(Delayed delayed) {
//            // 根据过期时间降序出队
//            int compare = Math.toIntExact((this.getDelay(TimeUnit.MILLISECONDS) - delayed.getDelay(TimeUnit.MILLISECONDS)));
//            return -compare;
//        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getMag() {
            return mag;
        }

        public void setMag(String mag) {
            this.mag = mag;
        }

        public long getExpire() {
            return expire;
        }

        public void setExpire(long expire) {
            this.expire = expire;
        }
    }
}