Java延时任务执行 - DelayQueue实现

编程教程 > Java (25) 2025-01-21 16:51:00

DelayQueue 简介

DelayQueue是JDK提供的api,是一个延迟队列

Java延时任务执行 - DelayQueue实现_图示-ce5a6ceaf23145b193d7aca21624d7b1.png

DelayQueue泛型参数得实现Delayed接口,Delayed继承了Comparable接口。

Java延时任务执行 - DelayQueue实现_图示-45f66da4feae4e0dbe01d57cefe43014.png

 

  • getDelay 方法返回这个任务还剩多久时间可以执行,小于0的时候说明可以这个延迟任务到了执行的时间了。
  • compareTo 这个是对任务排序的,保证最先到延迟时间的任务排到队列的头

 

Demo

@Data
public class DemoTask implements Delayed {
    String name;
    /**
     * 任务关键数据
     */
    List<Long> dataIds;
    Long delayMillis;

    public DemoTask(String name, List<Long> dataIds, Duration delaySeconds) {
        this.name = name;
        this.dataIds = dataIds;
        this.delayMillis = System.currentTimeMillis() + delaySeconds.toMillis();
    }


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

    @Override
    public int compareTo(Delayed o) {
        return this.delayMillis.compareTo(((DemoTask) o).delayMillis);
    }

}

SanYouTask实现了Delayed接口,构造参数

  • taskContent:延迟任务的具体的内容
  • delayTime:延迟时间,秒为单位

测试

@Slf4j
public class DelayQueueDemo {
    public static void main(String[] args) {
        DelayQueue<DemoTask> delayQueue = new DelayQueue<>();
        new Thread(() -> {
            while (true) {
                try {
                    DemoTask take = delayQueue.take();
                    List<Long> dataIds = take.getDataIds();
                    String name = take.getName();
                    log.info("任务名:{}", name);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();

        //提交任务
        delayQueue.offer(new DemoTask("任务1", Arrays.asList(1L,2L), Duration.ofSeconds(3L)));
        delayQueue.offer(new DemoTask("任务2", Arrays.asList(1L,2L),Duration.ofSeconds(8L)));
        delayQueue.offer(new DemoTask("任务3", Arrays.asList(1L,2L),Duration.ofSeconds(10L)));
        log.info("任务提交完成...");

    }
}
Java延时任务执行 - DelayQueue实现_图示-5382ccbf0973405ea6e3cf14e7896996.png

 

可以看到三次任务的执行时间与我们预期的一致。分别在提交任务后的3秒/8秒/10秒开始执行

Java延时任务执行 - DelayQueue实现_图示-584ba8c0cf55418fa9de5077a024c777.png

 

  • offer方法在提交任务的时候,会通过根据compareTo的实现对任务进行排序,将最先需要被执行的任务放到队列头。

  • take方法获取任务的时候,会拿到队列头部的元素,也就是队列中最早需要被执行的任务,通过getDelay返回值判断任务是否需要被立刻执行,如果需要的话,就返回任务,如果不需要就会等待这个任务到延迟时间的剩余时间,当时间到了就会将任务返回。

 

注意事项 : 

这里的任务如果是同步,耗时较大可能回影响其他任务的准确性。所以根据实际情况考虑将任务异步化

修改任务内容,增加延时来看

new Thread(() -> {
    while (true) {
        try {
            DemoTask take = delayQueue.take();
            List<Long> dataIds = take.getDataIds();
            String name = take.getName();
            log.info("任务名:{}", name);
            //延时10s
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}).start();
Java延时任务执行 - DelayQueue实现_图示-765c69ec00044c739294359ed3cf2283.png
执行结果

从上面执行结果可以看到,同步任务耗时过多会影响其他后续任务执行时间。

 


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
DelayQueue 简介DelayQueue是JDK提供的api,是一个延迟队列DelayQueue泛型参数得实现Delayed接口,Delayed继承了Co
概述Timer/ScheduledThreadPoolExecutor都是是JDK提供的api Timer Demoimport lombok.extern.s
Java Queue队列使用入门详解
java Queue队列实现生产消费模式,什么是Java编程中的Queue(队列),手动实现生产者消费者模式
简述在本博客中,我们将会创建一个reids的消息队列,Redis可以被当成消息队列使用
Spring Boot定时任务阻塞解决方式一:修改定时任务的线程数量修改spring boot项目的application配置文件,将下面的配置修改为合适的值,默认1表示所有定时任务都是一个线程...
LinkedBlockingQueue 阻塞队列实现生产/消费模型package com.example.demospringbootqueueasynctask; import org....
在这篇文章中,我们将讨论有关使用异步任务执行程序功能在不同线程中执行任务的Spring boot异步执行支持。我们将看看在Spring项目中配置SimpleAsyncTaskExecutor,C...
java编程中​​​​​​​通过Timer配合TimeTask实现计划调度任务的使用
1. 线程的安全性问题:线程安全和非线程安全: 一个类在单线程环境下能够正常运行,并且在多线程环境下,使用方不做特别处理也能运行正常,我们就称其实线程安全的
Spring框架自带了一个任务调度器,虽然默认的方式只能通过配置写死,但是也可以自己适当运用
本文将讲述CLH锁的使用场景,什么情况适合使用CLH锁?Java 怎么使用CLH锁?
问题描述最近写JavaFX程序遇到了下面的错误:Exception in thread "pool-2-thread-1" java.lang.IllegalStateException: No...
try-with-resources是Java 7 引入的一个新功能,自动资源管理。try-with-resources语句的吸引力在于其“确保在语句结束时关闭每个资源“的保证。此上下文中的“资...
Spring Boot MQTT协议通过spring boot整合apache artemis实现Java语言MQTT协议通信,搭建MQTT服务器可以参考上一篇 MQTT Java入门-搭建MQ...