關(guān)于任務(wù)調(diào)度框架quartz使用(異常處理,解決恢復(fù)后多次調(diào)度處理)
首先先說(shuō)說(shuō)什么是調(diào)度框架
大白話所謂的調(diào)度框架你可以把它看成一個(gè)定時(shí)任務(wù)管理框架,并且quartz框架是多線程的,
quartz最主要的三大基本特性
(1)調(diào)度器 Scheduler(控制調(diào)度)
(2)Trigger(定義觸發(fā)的條件)這里的條件 ,可以用類似于‘0/20 * * * * ?’這種表達(dá)式來(lái)表示
(3)JobDetail & Job JobDetail 定義的是任務(wù)數(shù)據(jù),而真正的執(zhí)行邏輯是在Job中
首先看以下代碼講解了如何新增了一個(gè)調(diào)度任務(wù)
QuartzEntity quartz = new QuartzEntity();
quartz.setJobName("test01");
quartz.setJobGroup("test");
quartz.setDescription("測(cè)試任務(wù)");
quartz.setJobClassName("com.itstyle.quartz.job.ChickenJob");
quartz.setCronExpression("0/20 * * * * ?");
Class cls = Class.forName(quartz.getJobClassName()) ;
cls.newInstance();
//構(gòu)建job信息
JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(),
quartz.getJobGroup())
.withDescription(quartz.getDescription()).build();
// 觸發(fā)時(shí)間點(diǎn)
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger"+quartz.getJobName(), quartz.getJobGroup())
.startNow().withSchedule(cronScheduleBuilder).build();
//交由Scheduler安排觸發(fā)
scheduler.scheduleJob(job, trigger);不過(guò)這里有個(gè)問題!,那就是調(diào)度任務(wù)停止恢復(fù)后多次調(diào)度的問題。
如何解決,首先在properties配置一文件中配置一行代碼
org.quartz.jobStore.misfireThreshold = 5000
這里先介紹下 CronTrigger
這里有三種模式:
withMisfireHandlingInstructionDoNothing
- 不觸發(fā)立即執(zhí)行
- 等待下次Cron觸發(fā)頻率到達(dá)時(shí)刻開始按照Cron頻率依次執(zhí)行
withMisfireHandlingInstructionIgnoreMisfires
- 以錯(cuò)過(guò)的第一個(gè)頻率時(shí)間立刻開始執(zhí)行
- 重做錯(cuò)過(guò)的所有頻率周期后
- 當(dāng)下一次觸發(fā)頻率發(fā)生時(shí)間大于當(dāng)前時(shí)間后,再按照正常的Cron頻率依次執(zhí)行
withMisfireHandlingInstructionFireAndProceed
- 以當(dāng)前時(shí)間為觸發(fā)頻率立刻觸發(fā)一次執(zhí)行
- 然后按照Cron頻率依次執(zhí)行
我們用第一種模式,就是生成Trigger的時(shí)候添加第一種模式,以下為代碼可以參考下
QuartzEntity quartz = new QuartzEntity();
quartz.setJobName("test01");
quartz.setJobGroup("test");
quartz.setDescription("測(cè)試任務(wù)");
quartz.setJobClassName("com.itstyle.quartz.job.ChickenJob");
quartz.setCronExpression("0/20 * * * * ?");
Class cls = Class.forName(quartz.getJobClassName()) ;
cls.newInstance();
//構(gòu)建job信息
JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(),
quartz.getJobGroup())
.withDescription(quartz.getDescription()).build();
// 觸發(fā)時(shí)間點(diǎn)
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger"+quartz.getJobName(), quartz.getJobGroup())
.withSchedule(cronScheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
//交由Scheduler安排觸發(fā)
scheduler.scheduleJob(job, trigger);
好了,以上的方式就能解決恢復(fù)后多次調(diào)度的問題
停止調(diào)度:
try {
//quartz.getJobName() 代表任務(wù)id,quartz.getJobGroup()代表任務(wù)組
JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup());
scheduler.pauseJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
return Result.error();
}恢復(fù)調(diào)度:
try {
//quartz.getJobName() 代表任務(wù)id,quartz.getJobGroup()代表任務(wù)組
JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup());
scheduler.resumeJob(key);
} catch (SchedulerException e) {
e.printStackTrace();
return Result.error();
}刪除調(diào)度:
try {
//quartz.getJobName() 代表任務(wù)id,quartz.getJobGroup()代表任務(wù)組
TriggerKey triggerKey = TriggerKey.triggerKey(quartz.getJobName(), quartz.getJobGroup());
// 停止觸發(fā)器
scheduler.pauseTrigger(triggerKey);
// 移除觸發(fā)器
scheduler.unscheduleJob(triggerKey);
// 刪除任務(wù)
scheduler.deleteJob(JobKey.jobKey(quartz.getJobName(), quartz.getJobGroup()));
System.out.println("removeJob:"+JobKey.jobKey(quartz.getJobName()));
} catch (Exception e) {
e.printStackTrace();
return Result.error();
} 在調(diào)度過(guò)程中出現(xiàn)異常怎么辦,如何處理
請(qǐng)看以下代碼:
/**
* 實(shí)現(xiàn)序列化接口、防止重啟應(yīng)用出現(xiàn)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 {
//任務(wù)調(diào)度ID
String work = context.getJobDetail().getKey().getName();
try{
//定時(shí)器任務(wù)start
//定時(shí)器任務(wù)end
}catch (Exception e){
JobExecutionException e2 = new JobExecutionException(e);
//自動(dòng)停止job相關(guān)的觸發(fā)器,job停止
//e2.setUnscheduleAllTriggers(true);
//自動(dòng)任務(wù)報(bào)錯(cuò)繼續(xù)執(zhí)行
e2.setRefireImmediately(true);
LOGGER.error(e2.toString());
}
}
}這里分兩種有兩種方法:
//自動(dòng)停止job相關(guān)的觸發(fā)器,job停止 e2.setUnscheduleAllTriggers(true); //自動(dòng)任務(wù)報(bào)錯(cuò)繼續(xù)執(zhí)行 e2.setRefireImmediately(true);
總結(jié)
以上是關(guān)于調(diào)度任務(wù)出現(xiàn)異常后如何處理的相關(guān)代碼。
好了,這些為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用mybatis插件PageHelper實(shí)現(xiàn)分頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了使用mybatis插件PageHelper實(shí)現(xiàn)分頁(yè)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
mybatis中resultMap 標(biāo)簽的使用教程
resultMap 標(biāo)簽用來(lái)描述如何從數(shù)據(jù)庫(kù)結(jié)果集中來(lái)加載對(duì)象,這篇文章重點(diǎn)給大家介紹mybatis中resultMap 標(biāo)簽的使用,感興趣的朋友一起看看吧2018-07-07
SpringBoot整合sharding-jdbc實(shí)現(xiàn)分庫(kù)分表與讀寫分離的示例
本文主要介紹了SpringBoot整合sharding-jdbc實(shí)現(xiàn)分庫(kù)分表與讀寫分離的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
SpringBoot整合HikariCP數(shù)據(jù)庫(kù)連接池方式
這篇文章主要介紹了SpringBoot整合HikariCP數(shù)據(jù)庫(kù)連接池方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
Java實(shí)現(xiàn)微信網(wǎng)頁(yè)授權(quán)的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)微信網(wǎng)頁(yè)授權(quán)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
java基于控制臺(tái)的學(xué)生學(xué)籍管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java基于控制臺(tái)的學(xué)生學(xué)籍管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
Java Builder模式構(gòu)建MAP/LIST的實(shí)例講解
下面小編就為大家?guī)?lái)一篇Java Builder模式構(gòu)建MAP/LIST的實(shí)例講解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10

