前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >每日一博 - 延时任务的多种实现方式解读

每日一博 - 延时任务的多种实现方式解读

作者头像
小小工匠
发布2021-09-03 14:17:13
4160
发布2021-09-03 14:17:13
举报
文章被收录于专栏:小工匠聊架构

文章目录


Pre

每日一博 - 使用环形队列实现高效的延时消息


延时任务 VS 定时任务

举个例子,开发中常见的延时任务场景:

  • 半小时未支付,取消订单

延时任务和定时任务的几个小区别,梳理下:

  • 定时任务有明确的触发时间,延时任务没有
  • 定时任务有执行周期,而延时任务在某事件触发后一段时间内执行,没有执行周期
  • 定时任务一般执行的是批处理操作是多个任务,而延时任务一般是单个任务

Solutions

DB 轮询

核心思想

通过定时任务扫描,执行业务逻辑。


Demo Code

参考实现如下:

代码语言:javascript
复制
	 <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.2</version>
    </dependency>
代码语言:javascript
复制
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
 
public class MyJob implements Job {
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        System.out.println("模拟扫描任务。。。。。");
    }
 
    public static void main(String[] args) throws Exception {
        // 创建任务
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job1", "group1").build();
        // 创建触发器 每3秒钟执行一次
        Trigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity("trigger1", "group3")
                .withSchedule(
                        SimpleScheduleBuilder.simpleSchedule()
                                .withIntervalInSeconds(3).repeatForever())
                .build();
        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        // 将任务及其触发器放入调度器
        scheduler.scheduleJob(jobDetail, trigger);
        // 调度器开始调度任务
        scheduler.start();
    }
}

优缺点

优点: 简单 (好像也没有其他的优点了 哈哈哈 )

缺点:

  • (1)占用资源,对服务器内存消耗大
  • (2)存在延迟,比如你每隔n分钟扫描一次,那最坏的延迟时间就是n分钟
  • (3)如果表的数据量较大,每隔几分钟这样扫描一次,性能堪忧,DB压力较大

JDK的Delay Queue

核心思想

利用JDK自带的DelayQueue来实现, 无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入DelayQueue中的对象,必须实现Delayed接口。

  • poll():获取并移除队列的超时元素,没有则返回空
  • take():获取并移除队列的超时元素,如果没有则wait当前线程,直到有元素满足超时条件,返回结果。

Demo Code

代码语言:javascript
复制
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
 
public class TicketDelay implements Delayed {
    
    private String ticketId;
    private long timeout;
 
    OrderDelay(String ticketId, long timeout) {
        this.ticketId= ticketId;
        this.timeout = timeout + System.nanoTime();
    }
 
    public int compareTo(Delayed other) {
        if (other == this)
            return 0;
        OrderDelay t = (OrderDelay) other;
        long d = (getDelay(TimeUnit.NANOSECONDS) - t
                .getDelay(TimeUnit.NANOSECONDS));
        return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
    }
 
    // 返回距离你自定义的超时时间还有多少
    public long getDelay(TimeUnit unit) {
        return unit.convert(timeout - System.nanoTime(),TimeUnit.NANOSECONDS);
    }
 
    void print() {
        System.out.println(orderId+"编号的订单要删除啦。。。。");
    }
}

优缺点


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • Pre
  • 延时任务 VS 定时任务
  • Solutions
    • DB 轮询
      • 核心思想
      • Demo Code
      • 优缺点
    • JDK的Delay Queue
      • 核心思想
      • Demo Code
      • 优缺点
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档