项目场景:
项目场景:两个Quartz定时任务,当状态码为正常时,执行任务1;当状态码为预警或告警时,执行任务2。Springboot项目启动时,执行定时任务
问题描述
新建调度器实例时,直接调用getScheduler 会得到同一个实例,所以每次任务就会同时开启,同时关闭,没法根据需求调整
原因分析:
获取的scheduler是从仓储SchedulerRepository里面取出来的,仓储注册scheduler的时候为每个scheduler分配一个唯一的名字,问题就在于这里,Quartz默认有个配置文件quartz.properties,里面定义了这个名字,这样的话,每次通过sf.getScheduler()获取的都是同一个实例。
解决方案:
//自定义Schedulers实例 直接调用getScheduler 会得到同一个实例
StdSchedulerFactory sfact2 = new StdSchedulerFactory();
Properties props = new Properties();
props.put("org.quartz.scheduler.instanceName","hei");
props.put("org.quartz.threadPool.threadCount","10");
sfact2.initialize(props);
Scheduler scheduler2 = sfact2.getScheduler();
//调度器绑定任务和触发器
scheduler2.scheduleJob(jobDetail2, trigger2);
完整代码
依赖配置
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
状态码的枚举类:
package cn.smxy.testSpring.enums;
public enum EnumDataState {
NORMAL(0, "正常"),
EARLY_WARNING(1, "预警"),
ALARM(2, "报警"),
;
private final int code;
private final String desc;
EnumDataState(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
定时任务1:
package cn.smxy.testSpring.util;
/**
* @author nzh
* @date 2022/8/19 8:11
*/
import cn.hutool.core.date.DateUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class HelloJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("现在的时间是 : " + DateUtil.date());
System.out.println("hello world");
}
}
定时任务2:
package cn.smxy.testSpring.util;
import cn.hutool.core.date.DateUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author nzh
* @date 2022/8/19 8:30
*/
public class HeiJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 具体的业务逻辑
// java自带写法 打印当前时间
// Date date = new Date();
// SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// hutool写法
System.out.println("现在的时间 这里是2 : " + DateUtil.now());
System.out.println("hei bro fu**");
}
}
任务执行类:
package cn.smxy.testSpring.util;
/**
* @author nzh
* @date 2022/8/19 8:14
*/
import cn.hutool.core.date.DateUtil;
import cn.smxy.testSpring.enums.EnumDataState;
import lombok.SneakyThrows;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;
import java.util.Properties;
import java.util.Scanner;
@Component
public class HelloScheduler {
@SneakyThrows
public void quartz() {
//打印当前时间
System.out.println("现在的时间是(嘿嘿) : " + DateUtil.date());
//创建一个jobdetail实例,将该实例与hellojob类绑定
JobDetail jobDetail1 = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob1", "group1").build();
//创建一个jobdetail实例,将该实例与heijob类绑定
JobDetail jobDetail2 = JobBuilder.newJob(HeiJob.class)
.withIdentity("myJob2", "group2").build();
//触发器
CronTrigger trigger1 = (CronTrigger) TriggerBuilder.newTrigger()
.withIdentity("myTrigger1", "group1")
.withSchedule(
CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
.build();
CronTrigger trigger2 = (CronTrigger) TriggerBuilder.newTrigger()
.withIdentity("myTrigger2", "group2")
.withSchedule(
CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.build();
//创建Schedulers实例
SchedulerFactory sfact1 = new StdSchedulerFactory();
Scheduler scheduler1 = sfact1.getScheduler();
//调度器绑定任务和触发器
scheduler1.scheduleJob(jobDetail1, trigger1);
//自定义Schedulers实例 直接调用getScheduler 会得到同一个实例
StdSchedulerFactory sfact2 = new StdSchedulerFactory();
Properties props = new Properties();
props.put("org.quartz.scheduler.instanceName","hei");
props.put("org.quartz.threadPool.threadCount","10");
sfact2.initialize(props);
Scheduler scheduler2 = sfact2.getScheduler();
//调度器绑定任务和触发器
scheduler2.scheduleJob(jobDetail2, trigger2);
Scanner scanner = new Scanner(System.in);
for (; ; ) {
//启动scheduler
scheduler1.start();
//手动输入状态码 实际项目中 是接口返回的值
Integer ans = scanner.nextInt();
while (ans.equals(EnumDataState.EARLY_WARNING.getCode()) || ans.equals(EnumDataState.ALARM.getCode())) {
scheduler1.standby();
// 第二个Schedulers实例
scheduler2.start();
Integer ans1 = scanner.nextInt();
if (ans1.equals(EnumDataState.NORMAL.getCode())) {
scheduler2.standby();
break;
}
}
}
}
}
代码自启类
package cn.smxy.testSpring.service.impl;
import cn.smxy.testSpring.util.HelloScheduler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ApplicationRunnerImpl implements ApplicationRunner {
@Autowired
HelloScheduler helloScheduler;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("项目启动成功,执行操作");
helloScheduler.quartz();
System.out.println("冲冲冲,跑起来");
}
}