springBoot使用注解完成定时任务
1.在程序启动类上添加这个注解
/*定时器注解*/
@EnableScheduling
@SpringBootApplication
@MapperScan("com.aiwtc.pf.ticket.dao")
public class TicketApplication {
public static void main(String[] args) {
SpringApplication.run(TicketApplication.class, args);
}
}
2.建一个时间表任务的包,建一个定时任务的类,我这里是定时查询未支付订单,并修改其失效订单状态
/**
* 定时任务
*/
@Component
public class OrderPackageScheduleTask {
@Resource
MmOrderPackageService orderPackageService;
//添加定时任务15分钟操作一次数据库,cron的表达式生成参考:http://cron.qqe2.com/ =====写法也可以直接指定时间间隔,例如:5秒:@Scheduled(fixedRate=5000)====
1.fixedRate:定义一个按一定频率执行的定时任务,
2.fixedDelay:定义一个按一定频率执行的定时任务,与上面不同的是,改属性可以配合initialDelay, 定义该任务延迟执行时间。
3.cron:通过表达式来配置任务执行时间
@Scheduled(cron = "0 0/15 * * * ?")
private void configureTasks() {
//定时执行的,业务逻辑就在这里。自己测试的话,就可以只写几个,sout,然后定时时间写短点方便测试即可
//查询未支付订单
List<MmOrderPackage> orderPackageNotPay = orderPackageService.getOrderPackageNotPay();
for (MmOrderPackage orderPackage:orderPackageNotPay) {
//如果下单时间,距离现在超过30分钟,就将订单状态改为3.已过期
if(Long.valueOf(TimeService.currentTimeMilliStr()) - Long.valueOf(orderPackage.getCtime()) > TimeService.THIRTY_MILLISECONDS){
System.out.println("当前更新时间是:"+TimeService.currentTimeMilliStr());
System.out.println("还未完成支付,已过期的订单:id:"+orderPackage.getId()+"编号:"+orderPackage.getOid()+"订单名:"+orderPackage.getTitle());
orderPackageService.changeOrderPackagePayToOverdue(orderPackage.getId());
}
}
}
}
3.ojbk,一个究极简单的定时任务就这样了!,但是当定时任务过多时:如果一个任务卡死,会导致其他任务也无法执行。如:
@Scheduled(fixedRate = 5000)
public void scheduled1() {
log.info("=====>>>>>使用fixedRate{}", System.currentTimeMillis());
}
@Scheduled(fixedDelay = 5000)
public void scheduled2() {
log.info("=====>>>>>fixedDelay{}",System.currentTimeMillis());}
此时就可以多线程执行,依然使用注解配置线程:
@Configuration:表明该类是一个配置类
@EnableAsync:开启异步事件的支持
/**
* 线程池
* @author bl
*/
@Configuration
@EnableAsync
public class ThreadPool {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor threadTaskPool = new ThreadPoolTaskExecutor();
// 设置核心线程数
threadTaskPool.setCorePoolSize(10);
// 设置最大线程数
threadTaskPool.setMaxPoolSize(10);
// 设置队列容量
threadTaskPool.setQueueCapacity(10);
// 设置线程活跃时间300秒
threadTaskPool.setKeepAliveSeconds(300);
// 设置默认线程名称
threadTaskPool.setThreadNamePrefix("mmthread-");
// 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务 CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
threadTaskPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
threadTaskPool.setWaitForTasksToCompleteOnShutdown(true);
return threadTaskPool;
}
}
然后在定时任务的类或者方法上添加@Async,就是实现了多线程任务
4.补充:针对订单超出支付时间失效这个问题:
本项目的原理是:定时15分钟操作一次数据库,查出未支付订单,并判断是否过期,过期则修改状态。
这样只是简单的实现了,当然会有缺点:
1.时效性差,会有一定的延迟,这个延迟时间最大就是每隔一定时间的大小,即设置的定时任务时间
2.效率低,每次都要进行DB操作,可能会浪费资源。
3.所以这个方法适合小项目
但是暂时又没想到其他合适的方案。。。暂时用的这个!
5.更多,更优的方法,欢迎评论,共勉!