延时队列
延迟任务
延迟队列的出现就是为了延迟任务,所谓的延迟任务就是“在一个事件发生之后触发”,并且就执行一次,不具备周期执行的特征。因此延迟任务具备的特征:
1、发起事件的不确定性
2、执行的一次性
常见的延迟任务:
(1)淘宝对于订单生成之后,存在30min的延迟时间,在30min未支付则需要取消订单,因此取消订单就是一个延迟任务。
定时扫描数据库
对于未支付的订单,需要进行定期扫描,判断其产生时间有没有超过固定的时间,如果超过则取消订单。这样做,很明显很垃圾,因为:
(1)你说你扫描数据库,你知道在数据很多的情况下每次扫描整个表需要多长的时间么…,不仅浪费资源而且还时间很长
(2)所谓的定期扫描,扫描时间的粒度太小,就会造成资源浪费,扫描的粒度太大就会造成订单没有及时删除
虽然嘴上说着,扫库不行,但还是来做一个定时任务吧,学习一个quartz中的定时任务:
思路:基于quartz确定一个定时任务,该定时任务是定期扫库,看时间有没有超过3s的,有超过则…(删除)
public class ScanDatabase implements Job {
@Override
//定义任务
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//扫描用户表的加入时间,计算其入职时长,如果超过一定时间就输出
System.out.println("扫描数据库开始...");
try {
//getUserEntryTime()这个方法就是扫库的方法
List<String> entryTimes= DataBase.getUserEntryTime();
for(int i=0;i<entryTimes.size();i++){
String time=entryTimes.get(i);
DateFormat fmt=new SimpleDateFormat("yyyy-MM-dd");
Date entryTime=fmt.parse(time);
Date nowTime=new Date();
long diffTime=nowTime.getTime()-entryTime.getTime();
if(diffTime>3){
System.out.println("加入时间:"+time);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
//利用quartz做一个定时的扫描数据库的任务
public static void main(String[] args) throws SchedulerException {
JobDetail jobDetail= JobBuilder.newJob(ScanDatabase.class)
.withIdentity("job1","group1").build();
//创建触发器,每三秒种执行一次
Trigger trigger=TriggerBuilder.newTrigger()
.withIdentity("trigger1","group2")
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever()).build();//这里是每秒扫描一次
//创建调度器
Scheduler scheduler=new StdSchedulerFactory().getScheduler();
//将任务放在调度器中
scheduler.scheduleJob(jobDetail,trigger);
scheduler.start();
}
}
public class DataBase {
private static final String URL="jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai";
private static final String USER="root";
private static final String PASSWORD="****";
public static List getUserEntryTime(