Java 正在多次运行作业的调度程序

Java 正在多次运行作业的调度程序,java,spring,quartz-scheduler,cronexpression,Java,Spring,Quartz Scheduler,Cronexpression,我使用Quartz CronScheduler每15分钟执行一次作业。每次作业执行时,它都会检查数据库中cron表达式的任何更改,并为下次运行更新作业调度程序。我已通过以下方式实施了上述内容: @Service public class QuartzSchedulerService { private static final Logger LOG = LoggerFactory.getLogger(QuartzSchedulerService.class); private

我使用Quartz CronScheduler每15分钟执行一次作业。每次作业执行时,它都会检查数据库中cron表达式的任何更改,并为下次运行更新作业调度程序。我已通过以下方式实施了上述内容:

@Service
public class QuartzSchedulerService {

    private static final Logger LOG = LoggerFactory.getLogger(QuartzSchedulerService.class);

    private Scheduler           scheduler;

    @PostConstruct
    private void init() {
        try {
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();
        } catch (Exception e) {
            LOG.error("Unable to start quartz scheduler", e);
        }
    }

    @PreDestroy
    private void destroy() {
        try {
            scheduler.shutdown();
        } catch (Exception e) {
            LOG.error("Unable to shutdown quartz scheduler", e);
        }
    }

    public void registerCronJob(Class<? extends Job> jobClass, String cronExpression) {
        try {
            String jobName = jobClass.getSimpleName();
            CronScheduleBuilder cronBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName).build();
            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName).withSchedule(cronBuilder).build();
            scheduler.scheduleJob(jobDetail, cronTrigger);
            LOG.info("Registered Cron Job:" + jobName + " " + jobDetail.getKey());
        } catch (Exception e) {
            LOG.error("Unable to register cron job", e);
        }
    }

    public void updateCronSchedule(Class<? extends Job> jobClass, String cronExpression) {
        try {
            String jobName = jobClass.getSimpleName();
            CronScheduleBuilder cronBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            CronTrigger newCronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName).withSchedule(cronBuilder).build();
            scheduler.rescheduleJob(TriggerKey.triggerKey(jobName), newCronTrigger);
            LOG.info("Updated Cron Job:" + jobName + " " + newCronTrigger.getJobKey());
            LOG.info("Jobs executed: " + scheduler.getMetaData().getNumberOfJobsExecuted());
        } catch (Exception e) {
            LOG.error("Unable to reschedule cron job", e);
        }
    }

}
在上下文初始化期间调用loadAtStartup()方法,然后每15分钟调用一次execute()方法

使用的cron表达式是:
0 0/15*1/1**

现在,问题如下: 假设作业在3:00:00开始,它将在3:00:01之前执行尽可能多的次,而不是只执行一次

下一步作业将在3:15:00开始,并再次运行尽可能多的次数,直到3:15:01

作业每次执行的次数不同

我不确定是什么导致了这种行为。我已经用cronmaker测试了cron表达式


有人能指出这里的错误吗

既然cron表达式似乎正确,我想您的问题可能取决于您的工作逻辑,您是否尝试过其他工作?你为什么要在内部重新安排你的工作?@davioooh不,我没有..快速不-不能
0 0/15*1/1**简化为
0 0/15****-由于月日增量为1天?@AndersR.Bystrup是的,可以。。让我改变一下。我还启动了两个Tomcat,其中一个的代码与上面相同,而在另一个Tomcat中,重新加载不会更新cron计划,问题在第二个Tomcat中消失了。这可能意味着更新作业本身中的cron计划会导致某种问题。@sshntt我认为从作业内部重新计划作业可能会导致一些“递归灾难”:)因此我认为您需要创建一个单独的作业来进行检查,并在其中重新计划主作业
@Component
@DisallowConcurrentExecution
public class PropertiesReloadJob implements Job {

    private static final Logger    LOG = LoggerFactory.getLogger(PropertiesReloadJob.class);

    @Autowired
    private QuartzSchedulerService schedulerService;

    @Autowired
    private PropertiesService  propertiesService;

    public void loadAtStartup() {
        load();
        LOG.info("--- Registerting PropertiesReload Cron Job ---");
        schedulerService.registerCronJob(PropertiesReloadJob.class, propertiesService.getCacheReloadCronExpression());
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        load();
        LOG.info("--- Updating Pro Cron Job ---");
        schedulerService.updateCronSchedule(PropertiesReloadJob.class, propertiesService.getCacheReloadCronExpression());
    }

    public void load(){
          // Load properties from DB
    }