Quartz内部流程:
- 调度器启动:当调度器启动时,Quartz 从数据库中加载触发器并将它们保存在内存中。
- 时间计算:Quartz 根据触发器的调度规则(例如 cron 表达式)计算下一个触发时间,并将其保存在
NEXT_FIRE_TIME
字段中。- 触发任务:当当前时间达到
NEXT_FIRE_TIME
时,Quartz 触发相应的任务。- 更新时间:任务触发后,Quartz 更新
PREV_FIRE_TIME
为当前时间,并根据调度规则计算新的NEXT_FIRE_TIME
。
方式1:
修改配置文件,重启
quartz通过动态设置配置文件实现与数据库的同步,修改配置文件后重启服务
方式2:
直接修改 qrtz_cron_triggers
表中的 cron_expression
字段。无需重启
可能不会生效,因为 Quartz 框架通常在启动时加载调度任务,并在运行时将它们缓存在内存中。因此,直接修改数据库表不会立即影响已经加载到内存中的调度任务。
重启应用程序可能会生效,也可能不生效,,表qrtz_triggers中的所有时间相关的值并没有变动,取决于qrtz_triggers的NEXT_FIRE_TIME和PREV_FIRE_TIME。
在 Quartz 中,
NEXT_FIRE_TIME
和PREV_FIRE_TIME
是用来记录触发器的下一次和上一次触发时间的字段。如果修改了cron_expression
,可能需要手动更新这些字段,这些字段通常是由 Quartz 自动管理的,并且通过 Quartz API 更新触发器时会自动更新。
手动修改时间(不需要重启)
表qrtz_triggers中的下一次执行的时间NEXT_FIRE_TIME和上一次执行的时间PREV_FIRE_TIME值改为0,而且执行任务后对应的相关时间值都变成了表qrtz_cron_triggers当前cronExpression值对应的时间(不会立即生效,可能会几分钟生效)。
1.修改qrtz_cron_triggers的cronExpression
UPDATE ]`qrtz_cron_triggers` SET `CRON_EXPRESSION` = '0 59 23 * * ?' WHERE `TRIGGER_NAME` = 'DockerUserNfsStoreDeductionTrigger'
2.修改下一次执行时间和上一次执行时间
UPDATE `qrtz_triggers` SET `NEXT_FIRE_TIME` = 0,`PREV_FIRE_TIME` = 0 WHERE `TRIGGER_NAME` = 'DockerUserNfsStoreDeductionTrigger'
过几分钟后NEXT_FIRE_TIME变为设置定时任务的时间
NEXT_FIRE_TIME 的单位是毫秒,将1720799940000/1000=1720799940秒,转换位时间如下
当23:59任务触发后,Quartz 更新 PREV_FIRE_TIME
为当前时间,并根据调度规则计算新的 NEXT_FIRE_TIME
。
注意:测试后最后再执行一次数据,恢复原来的定时任务时间
生产上不建议这么做,如果手动将
NEXT_FIRE_TIME
和PREV_FIRE_TIME
修改为 0,Quartz 在下次检查触发器时可能会忽略这些任务或引发错误。Quartz 期望这些字段包含有效的时间戳,设置为 0 可能会导致意外行为直接修改数据库字段虽然可以实现需要的效果,但应谨慎使用,因为这可能会破坏 Quartz 的内部状态一致性。更推荐使用 Quartz API 来管理和更新调度任务。
方式3:
安全触发:通过 Quartz API 来重新调度任务。
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzExample {
public static void main(String[] args) throws SchedulerException {
// 获取调度器实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 启动调度器
scheduler.start();
// 创建 TriggerKey
TriggerKey triggerKey = new TriggerKey("triggerName", "triggerGroup");
// 获取当前触发器
CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 使用新的 cron 表达式创建新的触发器
TriggerBuilder<CronTrigger> tb = oldTrigger.getTriggerBuilder();
CronTrigger newTrigger = tb.withSchedule(CronScheduleBuilder.cronSchedule("newCronExpression")).build();
// 重新调度触发器
scheduler.rescheduleJob(triggerKey, newTrigger);
// 打印新的 NEXT_FIRE_TIME 和 PREV_FIRE_TIME
System.out.println("Next Fire Time: " + newTrigger.getNextFireTime());
System.out.println("Previous Fire Time: " + oldTrigger.getPreviousFireTime());
// 停止调度器
scheduler.shutdown();
}
}