My English is not very good, I use Google Translate, which may cause trouble for everyone's reading, sorry
I want to use quartz to implement a scheduled push task, but there are some problems;
I will show my problems and attempts now, hoping to get help from everyone, thank you!
I am not using a database for persistence , here is my test code for adding task,some location pointers that need to push data are recorded in the JobDataMap
@Override
public int addJob(JobInfo jobInfo) {
int result = 0;
int isJobExist = this.isJobExist(JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup()));
if (isJobExist == 1) {
result = -1;
log.info("Task already exists");
} else {
try {
JobDetail jobDetail = null;
if (isJobExist == 0) {
jobDetail = scheduler.getJobDetail(JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup()));
} else if (isJobExist == -1) {
jobDetail = JobBuilder.newJob(
(Class<? extends QuartzJobBean>) Class.forName(jobInfo.getJobClassname()))
.withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup())
.withDescription(jobInfo.getDescription())
.storeDurably(jobInfo.isDurability()).build();
if(jobInfo.getNpcParam() != null){
jobDetail.getJobDataMap().put(NpcParam.NPC_JOB_PARAM, jobInfo.getNpcParam());
}
}
// If the cron expression of jobInfo is empty, a regular task will be created,
// otherwise a periodic task will be created
if (!StringUtils.isEmpty(jobInfo.getCronExpression())) {
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity(jobInfo.getTriggerName(), jobInfo.getTriggerGroup())
.withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCronExpression()))
.build();
scheduler.scheduleJob(jobDetail, cronTrigger);
} else {
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup())
.startAt(sdf.parse(jobInfo.getNextFireTime()))
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0))
.build();
scheduler.scheduleJob(jobDetail, trigger);
}
} catch (ClassNotFoundException e) {
result = 1;
log.error("The Class corresponding to the task does not exist!");
} catch (SchedulerException e) {
result = 2;
e.printStackTrace();
log.error("task scheduling failed");
} catch (ParseException e) {
result = 3;
log.error("time conversion error");
}
}
return result;
}
pause method
scheduler.pauseJob(JobKey.jobKey(jobName, jobGroup));
resume method
scheduler.resumeJob(JobKey.jobKey(jobName, jobGroup));
But this will cause the problem in the title, the data will be pushed to the front end soon
I try to delete the job while suspending the job, get the location pointer of the pushed data before deleting, and create a new job when continuing.
While this solves the above problem, I think there may be hidden dangers:
Quartz deletes the job and waits for the execution of the current job to complete. The deleted job and the scheduled job are two different threads, but I cannot ensure that the obtained location pointer is the latest, which will cause a set of already pushed data to be pushed next time.
I think I found a solution. I added the quartz.properties file in the resources directory of the project and set the following content
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
org.quartz.jobStore.misfireThreshold=100
# others
In this way, I will not redo the work when I resume after a period of suspension, and the artificial operation can hardly be faster than 100ms
Quartz scheduler misfire instructions explained
I didn't add it to quartz.properties at first, but I set properties in SchedulerFactoryBean, but it didn't seem to take effect
For thread safety issues, I choose to lock for different jobkeys