启动程序后可以看到,调度器已经启动:
2021-10-06 16:26:05.162INFO 10764 --- [shivaScheduler]] o.s.s.quartz.SchedulerFactoryBean: Starting Quartz Scheduler now, after delay of 1 seconds2021-10-06 16:26:05.306INFO 10764 --- [shivaScheduler]] org.quartz.core.QuartzScheduler: Scheduler shivaScheduler_$_DESKTOP-OKMJ1351633508761366 started.
新增调度任务添加任务,使用如下 json 进行请求:
{"concurrent": "1","cronExpression": "0/10 * * * * ?","invokeTarget": "mysqlJob.execute('got it!!!')","jobGroup": "mysqlGroup","jobId": 9,"jobName": "新增 mysqlJob 任务","misfirePolicy": "1","remark": "","status": "0"}
@Override@Transactional(rollbackFor = Exception.class)public int insertJob(QuartzJob job) throws Exception {// 先将任务设置为暂停状态job.setStatus(ScheduleConstants.Status.PAUSE.getValue());int rows = quartzMapper.insert(job);if (rows > 0) {ScheduleUtils.createScheduleJob(scheduler, job);}return rows;}
先将任务设置为暂停状态,数据库插入成功后,在调度器创建任务 。
再手动启动任务,根据 ID 来启动任务:
文章插图
实现代码:
@Overridepublic int changeStatus(Long jobId, String status) throws SchedulerException {int rows = quartzMapper.changeStatus(jobId, status);if (rows == 0) {return rows;}//更新成功,需要改调度器内任务的状态//拿到整个任务QuartzJob job = quartzMapper.selectJobById(jobId);//根据状态来启动或者关闭if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) {rows = resumeJob(job);} else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) {rows = pauseJob(job);}return rows;}
@Overridepublic int resumeJob(QuartzJob job) throws SchedulerException {Long jobId = job.getJobId();String jobGroup = job.getJobGroup();job.setStatus(ScheduleConstants.Status.NORMAL.getValue());int rows = quartzMapper.updateById(job);if (rows > 0) {scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));}return rows;}
暂停任务的代码也相同 。调用启动后可以看到控制台打印日志:
2021-10-06 20:36:30.018INFO 8536 --- [eduler_Worker-3] cn.shiva.quartz.job.MysqlJob: 执行 Mysql Job,当前时间:2021-10-06 20:36:30,任务参数:got it!!!2021-10-06 20:36:40.016INFO 8536 --- [eduler_Worker-4] cn.shiva.quartz.job.MysqlJob: 执行 Mysql Job,当前时间:2021-10-06 20:36:40,任务参数:got it!!!2021-10-06 20:36:50.017INFO 8536 --- [eduler_Worker-5] cn.shiva.quartz.job.MysqlJob: 执行 Mysql Job,当前时间:2021-10-06 20:36:50,任务参数:got it!!!
如果涉及到任务修改,需要在调度器先删除原有任务,重新创建调度任务 。启动初始化任务这部分倒是比较简单,初始化的时候清空原有任务,重新创建就好了:
/*** 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)*/@PostConstructpublic void init() throws Exception {scheduler.clear();List<QuartzJob> jobList = quartzMapper.selectJobAll();for (QuartzJob job : jobList) {ScheduleUtils.createScheduleJob(scheduler, job);}}
其他说明并发执行上面有并发和非并发的区别,通过 @DisallowConcurrentExecution 注解来实现阻止并发 。Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞 。
@DisallowConcurrentExecution 禁止并发执行多个相同定义的JobDetail, 这个注解是加在Job类上的, 但意思并不是不能同时执行多个Job, 而是不能并发执行同一个Job Definition(由JobDetail定义), 但是可以同时执行多个不同的JobDetail 。
举例说明,我们有一个Job类,叫做SayHelloJob, 并在这个Job上加了这个注解, 然后在这个Job上定义了很多个JobDetail, 如sayHelloToJoeJobDetail, sayHelloToMikeJobDetail, 那么当scheduler启动时, 不会并发执行多个sayHelloToJoeJobDetail或者sayHelloToMikeJobDetail, 但可以同时执行sayHelloToJoeJobDetail跟sayHelloToMikeJobDetail
@PersistJobDataAfterExecution 同样, 也是加在Job上 。表示当正常执行完Job后, JobDataMap中的数据应该被改动, 以被下一次调用时用 。
当使用 @PersistJobDataAfterExecution 注解时, 为了避免并发时, 存储数据造成混乱, 强烈建议把 @DisallowConcurrentExecution 注解也加上 。
推荐阅读
- 超跑|3.5秒破百的V12怪兽!阿斯顿马丁新超跑限量249辆已卖空
- 穿衣搭配|海清母子同框,“蛋妞”身材纤细很绅士,她留超短发很俏皮
- 华为|269元 李小龙力荐华为S-Tag运动传感器:详细记录跑步数据
- iPhone长篇笔记文章,怎么截成超长图片分享给别人?
- 超磁分离水体净化技术 超磁分离技术
- 穿衣搭配|50+想要穿出高级感,快来和这位姐妹学习,普通单品都能超神
- 勒布朗·詹姆斯|这就是超巨!半职业联赛席无空座,苦等詹姆斯12小时,球迷:都值得
- TCP/IP攻击详细解释
- 孕早期阴超有什么危害
- 孕12周前总共做15次b超