在Quartz中,一旦创建了一个触发器(Trigger),它会按照设定的时间表执行与之关联的作业(Job)。当项目启动时,Quartz调度器会检查所有的触发器,如果有任何一个触发器的开始时间在当前时间之前,那么与这个触发器关联的作业将会立即执行一次。
如果触发器的开始时间非常接近当前时间,例如只相差几秒,那么在项目启动后确实可能会出现多次执行作业的情况。这是因为在极短的时间间隔内,Quartz调度器可能会多次检查并执行与触发器相关联的作业。(本次由于某种原因,项目中设置的定时任务在创建后,出现了几十秒的延迟调度情况,但是调度时间又设置的很短,导致的在延迟结束后,触发器多次执行相关联的作业)
// 如果设定的定时时间很短
String cronExpression = "0/6 * * * * ? ";
sched.start();
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName)
.getClass())
.withIdentity(jobClassName)
.storeDurably()
.build();
// 表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger","group1")
.withSchedule(scheduleBuilder)
.forJob(jobDetail)
// 60秒后生效,要不然调度启动后如果延迟,可能出现首次执行多遍job
.startAt(DateBuilder.futureDate(60, DateBuilder.IntervalUnit.SECOND))
.usingJobData("parameter",parameter)
.build();
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
sched.addJob(jobDetail, true);
sched.scheduleJob(trigger);
// .startAt(DateBuilder.futureDate(60, DateBuilder.IntervalUnit.SECOND))
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger","group1")
.withSchedule(scheduleBuilder)
.forJob(jobDetail)
.startNow()
// 60秒后生效,要不然调度启动后如果延迟,可能出现首次执行多遍job
.startAt(DateBuilder.futureDate(60, DateBuilder.IntervalUnit.SECOND))
.usingJobData("parameter",parameter)
.build();