关于任务调度框架quartz使用(异常处理,解决恢复后多次调度处理)
首先先说说什么是调度框架
大白话所谓的调度框架你可以把它看成一个定时任务管理框架,并且quartz框架是多线程的,
quartz最主要的三大基本特性
(1)调度器 Scheduler(控制调度)
(2)Trigger(定义触发的条件)这里的条件 ,可以用类似于‘0/20 * * * * ?’这种表达式来表示
(3)JobDetail & Job JobDetail 定义的是任务数据,而真正的执行逻辑是在Job中
首先看以下代码讲解了如何新增了一个调度任务
QuartzEntity quartz = new QuartzEntity(); quartz.setJobName("test01"); quartz.setJobGroup("test"); quartz.setDescription("测试任务"); quartz.setJobClassName("com.itstyle.quartz.job.ChickenJob"); quartz.setCronExpression("0/20 * * * * ?"); Class cls = Class.forName(quartz.getJobClassName()) ; cls.newInstance(); //构建job信息 JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(), quartz.getJobGroup()) .withDescription(quartz.getDescription()).build(); // 触发时间点 CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression()); Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger"+quartz.getJobName(), quartz.getJobGroup()) .startNow().withSchedule(cronScheduleBuilder).build(); //交由Scheduler安排触发 scheduler.scheduleJob(job, trigger);
不过这里有个问题!,那就是调度任务停止恢复后多次调度的问题。
如何解决,首先在properties配置一文件中配置一行代码
org.quartz.jobStore.misfireThreshold = 5000
这里先介绍下 CronTrigger
这里有三种模式:
withMisfireHandlingInstructionDoNothing
- 不触发立即执行
- 等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
withMisfireHandlingInstructionIgnoreMisfires
- 以错过的第一个频率时间立刻开始执行
- 重做错过的所有频率周期后
- 当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行
withMisfireHandlingInstructionFireAndProceed
- 以当前时间为触发频率立刻触发一次执行
- 然后按照Cron频率依次执行
我们用第一种模式,就是生成Trigger的时候添加第一种模式,以下为代码可以参考下
QuartzEntity quartz = new QuartzEntity(); quartz.setJobName("test01"); quartz.setJobGroup("test"); quartz.setDescription("测试任务"); quartz.setJobClassName("com.itstyle.quartz.job.ChickenJob"); quartz.setCronExpression("0/20 * * * * ?"); Class cls = Class.forName(quartz.getJobClassName()) ; cls.newInstance(); //构建job信息 JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(), quartz.getJobGroup()) .withDescription(quartz.getDescription()).build(); // 触发时间点 CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression()); Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger"+quartz.getJobName(), quartz.getJobGroup()) .withSchedule(cronScheduleBuilder.withMisfireHandlingInstructionDoNothing()).build(); //交由Scheduler安排触发 scheduler.scheduleJob(job, trigger);
好了,以上的方式就能解决恢复后多次调度的问题
停止调度:
try { //quartz.getJobName() 代表任务id,quartz.getJobGroup()代表任务组 JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup()); scheduler.pauseJob(key); } catch (SchedulerException e) { e.printStackTrace(); return Result.error(); }
恢复调度:
try { //quartz.getJobName() 代表任务id,quartz.getJobGroup()代表任务组 JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup()); scheduler.resumeJob(key); } catch (SchedulerException e) { e.printStackTrace(); return Result.error(); }
删除调度:
try { //quartz.getJobName() 代表任务id,quartz.getJobGroup()代表任务组 TriggerKey triggerKey = TriggerKey.triggerKey(quartz.getJobName(), quartz.getJobGroup()); // 停止触发器 scheduler.pauseTrigger(triggerKey); // 移除触发器 scheduler.unscheduleJob(triggerKey); // 删除任务 scheduler.deleteJob(JobKey.jobKey(quartz.getJobName(), quartz.getJobGroup())); System.out.println("removeJob:"+JobKey.jobKey(quartz.getJobName())); } catch (Exception e) { e.printStackTrace(); return Result.error(); }
在调度过程中出现异常怎么办,如何处理
请看以下代码:
/** * 实现序列化接口、防止重启应用出现quartz Couldn't retrieve job because a required class was not found 的问题 */ public class TestJob extends AddXxBase implements Job,Serializable { private final static Logger LOGGER = LoggerFactory.getLogger(TestJob.class); private static final long serialVersionUID = 1L; /** * 模板 * **/ @Override public void execute(JobExecutionContext context) throws JobExecutionException { //任务调度ID String work = context.getJobDetail().getKey().getName(); try{ //定时器任务start //定时器任务end }catch (Exception e){ JobExecutionException e2 = new JobExecutionException(e); //自动停止job相关的触发器,job停止 //e2.setUnscheduleAllTriggers(true); //自动任务报错继续执行 e2.setRefireImmediately(true); LOGGER.error(e2.toString()); } } }
这里分两种有两种方法:
//自动停止job相关的触发器,job停止 e2.setUnscheduleAllTriggers(true); //自动任务报错继续执行 e2.setRefireImmediately(true);
总结
以上是关于调度任务出现异常后如何处理的相关代码。
好了,这些为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
SpringBoot项目读取外置logback配置文件的问题及解决
SpringBoot项目读取外置logback配置文件的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-08-08Java Thread.currentThread().getName() 和 this.getName()区别详
本文主要介绍了Thread.currentThread().getName() 和 this.getName()区别详解,TestThread testThread = new TestThread();2022-02-02利用Spring Boot和JPA创建GraphQL API
这篇文章主要介绍了利用Spring Boot和JPA创建GraphQL API,GraphQL既是API查询语言,也是使用当前数据执行这些查询的运行时,下文更多相关内容介绍需要的小伙伴可以参考一下2022-04-04聊聊在获取方法参数名方面,Spring真的就比Mybatis强?
在获取方法参数名方面,Spring真的就比Mybatis强吗?今天就带大家聊聊这个话题,如有错误或未考虑完全的地方,望不吝赐教2021-12-12
最新评论