当前位置: 首页 > article >正文

【SpringBoot】调度和执行定时任务--DelayQueue (附demo)

DelayQueue 是 Java 中 java.util.concurrent 包的一部分,它是一个无界阻塞队列,其中的元素只能在其到期时才能被取出。DelayQueue 是一个泛型类,要求队列中的元素实现 Delayed 接口。

1. Delayed 接口

要使用 DelayQueue,首先需要实现 Delayed 接口。Delayed 接口继承自 Comparable 接口,要求实现以下两个方法:

  • long getDelay(TimeUnit unit): 返回剩余的延迟时间。
  • int compareTo(Delayed o): 比较两个延迟对象的顺序。

2. 创建一个 Delayed 元素

下面是一个简单的实现 Delayed 接口的类:

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

public class DelayedElement implements Delayed {
    private final long delayTime;
    private final long expireTime;
    private final String message;

    public DelayedElement(long delayTime, String message) {
        this.delayTime = delayTime;
        this.expireTime = System.currentTimeMillis() + delayTime;
        this.message = message;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = expireTime - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        if (this.expireTime < ((DelayedElement) o).expireTime) {
            return -1;
        }
        if (this.expireTime > ((DelayedElement) o).expireTime) {
            return 1;
        }
        return 0;
    }

    public String getMessage() {
        return message;
    }
}

3. 使用 DelayQueue

创建一个 DelayQueue 并添加 Delayed 元素:

import java.util.concurrent.DelayQueue;

public class DelayQueueExample {
    public static void main(String[] args) throws InterruptedException {
        DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();

        // 添加延迟元素到队列中
        delayQueue.put(new DelayedElement(5000, "Message 1")); // 5秒延迟
        delayQueue.put(new DelayedElement(10000, "Message 2")); // 10秒延迟
        delayQueue.put(new DelayedElement(15000, "Message 3")); // 15秒延迟

        // 取出元素
        while (!delayQueue.isEmpty()) {
            DelayedElement element = delayQueue.take(); // 阻塞,直到有元素到期
            System.out.println("Received: " + element.getMessage());
        }
    }
}

4. 常用方法

DelayQueue 提供了一些常用的方法:

  • boolean add(E e): 添加元素到队列中。
  • boolean offer(E e): 尝试添加元素到队列中。
  • void put(E e): 添加元素到队列中,如果队列已满则阻塞。
  • E take(): 取出并移除队列头部的元素,如果没有元素到期则阻塞。
  • E poll(): 取出并移除队列头部的元素,如果没有元素到期返回 null
  • E peek(): 获取队列头部的元素,但不移除,如果没有元素到期返回 null
  • int size(): 返回队列中元素的数量。

5. 示例:使用 DelayQueue 实现延迟任务调度

下面是一个使用 DelayQueue 实现延迟任务调度的示例:

import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DelayQueueScheduler {
    private final DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();
    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    public DelayQueueScheduler() {
        executor.execute(() -> {
            try {
                while (true) {
                    DelayedElement element = delayQueue.take();
                    System.out.println("Executing task: " + element.getMessage());
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
    }

    public void scheduleTask(long delay, String message) {
        delayQueue.put(new DelayedElement(delay, message));
    }

    public void shutdown() {
        executor.shutdown();
    }

    public static void main(String[] args) throws InterruptedException {
        DelayQueueScheduler scheduler = new DelayQueueScheduler();
        scheduler.scheduleTask(5000, "Task 1"); // 5秒后执行
        scheduler.scheduleTask(10000, "Task 2"); // 10秒后执行
        scheduler.scheduleTask(15000, "Task 3"); // 15秒后执行

        Thread.sleep(20000); // 主线程等待20秒
        scheduler.shutdown();
    }
}

6. 注意事项

  • DelayQueue 是无界队列,因此在使用时要小心避免内存泄漏。
  • DelayQueue 中的元素必须实现 Delayed 接口,否则无法正常工作。
  • DelayQueuetake 方法是阻塞的,会一直等待直到有元素到期。

通过这些详细的用法和示例,你可以了解如何在Java中使用 DelayQueue 来实现延迟任务调度。根据具体需求选择合适的调度方法和处理策略。


http://www.kler.cn/news/304362.html

相关文章:

  • STM32——看门狗通俗解析
  • 【Linux网络】详解TCP协议(1)
  • C++特性--动态内存和智能指针
  • 工作睡觉监测识别摄像机
  • fly专享
  • 【三】TDengine 3.3.2 生产级别集群搭建
  • 【互联网的低潮期】
  • 相亲交友中的用户画像构建方法探讨
  • 【拥抱AI】使用Conda的一些常见命令
  • 如何判断硬盘是不是固态硬盘?介绍几种简单有效方法
  • Java多线程——模拟看病叫号
  • 聚鼎科技:现在做装饰画是靠谱的吗
  • pandas读取xlsx文件使用sqlachemy写到数据库
  • YOLOv5改进 | 模块缝合 | C3 融合RFAConv和CBAM注意力机制 【二次融合 小白必备】
  • 通过 汇编 分析 结构体
  • MongoDB根据字段内容长度查询语句
  • k8s 部署 ruoyi 前后端分离项目
  • 《企业实战分享 · SonarQube10.x 详细教程》
  • React 组件的基本使用,useState 状态变量的使用
  • 【Linux基础】02 权限
  • VUE+Tailwind网页开发
  • 大数据中一些常用的集群启停命令
  • oracle 如何查询表被锁
  • Vue自定义组件:解密v-model,轻松实现双向数据绑定
  • Nacos rce-0day漏洞复现(nacos 2.3.2)
  • 如何准备技术面试?
  • 利用AI驱动智能BI数据可视化-深度评测Amazon Quicksight(二)
  • Stream流的思想和获取Stream流
  • 设计模式重新整理
  • 中秋出游热度十足!喆啡酒店如何巧妙捕捉多元旅游需求?