每日一博 - 延时任务的多种实现方式解读
Posted 小小工匠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一博 - 延时任务的多种实现方式解读相关的知识,希望对你有一定的参考价值。
文章目录
Pre
延时任务 VS 定时任务
举个例子,开发中常见的延时任务场景:
- 半小时未支付,取消订单
- …
延时任务和定时任务的几个小区别,梳理下:
- 定时任务有明确的触发时间,延时任务没有
- 定时任务有执行周期,而延时任务在某事件触发后一段时间内执行,没有执行周期
- 定时任务一般执行的是批处理操作是多个任务,而延时任务一般是单个任务
- …
Solutions
DB 轮询
核心思想
通过定时任务扫描,执行业务逻辑。
Demo Code
参考实现如下:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.2</version>
</dependency>
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
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+"编号的订单要删除啦。。。。");
}
}
优缺点
时间轮算法
核心思想
Demo Code
优缺点
核心思想
Demo Code
优缺点
以上是关于每日一博 - 延时任务的多种实现方式解读的主要内容,如果未能解决你的问题,请参考以下文章