繁体   English   中英

Spring的@Scheduled cron作业在预定时间之前触发了几毫秒

[英]Spring's @Scheduled cron job is triggering a few milliseconds before the scheduled time

我已经设置了Spring的@Scheduled ,每小时都有一个cron表达式,如下所示: trend.olap.local.loading.cron.expression0 0 * * * ?

@Scheduled(cron = "${trend.olap.local.loading.cron.expression}")
public void loadHoulyDataToLocalOlap() {
    try {
        // To calculate prev hour;
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.HOUR, -1);
        Date date = cal.getTime();
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Loading hourly data into local olap :" + date
                    + ", and hour :" + hour);
        }

        dataIntegrationProcessor.loadHourlyDataToLocalOlap(hour);

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Loading hourly data into local olap :" + date
                    + ", and hour :" + hour + " Completed.");
        }
    } catch (Exception e) {
        LOGGER.error("Error occured at loadHoulyDataToLocalOlap", e);
    }
}

这里我的目的是从当前日期和时间获取小时值并将其传递给执行程序方法。

基本上我采取当前小时减1,所以在17:00,小时值应该是16。

但是如果你看到日志,则小时值为15.这是因为调度程序运行在16:59:59,831左右。 请参阅下面的log4j日志。 看起来cron作业在几毫秒内完成并在17:00:00,000之前的几毫秒内被触发。

因此,我得到了错误的价值观,而我的商业案例也失败了。

如何让cron在每小时的零毫秒内完全运行,而不是在几毫秒之前?

DEBUG 2013-09-29 16:59:59,831 (TrendScheduler.java loadHoulyDataToLocalOlap:57) - Loading hourly data into local olap :Sun Sep 29 15:59:59 IST 2013, and hour :15
DEBUG 2013-09-29 16:59:59,831 (DataIntegrationProcessor.java loadHourlyDataToLocalOlap:57) - Loading hourly data for hour :15
INFO 2013-09-29 17:00:00,054 (KettleJobExecutor.java executeJob:73) - Job (24hr_populate_hour_data_job.kjb) executed successfully
DEBUG 2013-09-29 17:00:00,054 (TrendScheduler.java loadHoulyDataToLocalOlap:64) - Loading hourly data into local olap :Sun Sep 29 15:59:59 IST 2013, and hour :15 Completed.

简短的回答是你不能使用cron选项。 cron表达式的分辨率是第二个,因此它将舍入到最接近的秒。 您可能能够保证它至少在特定时间之后发生,但与cron完全不同。

您最好的选择是实现自己的Trigger Trigger接口有一个方法,它返回java.util.Date以供下次执行(以毫秒为单位)。 从那里你可以注册任务和触发器,如下面的文档所示: http//docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableScheduling.html

如果您打算插入正确的小时值,我认为更好的解决方案是根据可预测性较低的cron计划计算小时数。 只要它落在一秒钟之内,您就可以简单地获取当前时间并将其转换为最接近的小时,然后从那里获取小时值。 您还可以添加警告/警报,通过收听迟到超过一分钟或迟到10分钟等的任务,让您知道cron是否表现不稳定。

虽然你可以改为调整cron时间表,但我认为这比在代码中处理它更多,因为你在这一点上近似了近似值。 您可以在代码中拥有更多控制权来处理超过100毫秒的简单偏移

假设没有任何其他时序问题,例如系统突然加载,Cron将忽略毫秒并暗示只能精确到一秒钟内。

您有两个选择:1。在小时后几秒钟启动cron作业2.更改小时计算以允许提前触发作业。

在这两个中,第一个是最简单的,我不会把它称为比使用浮点数时允许舍入问题更黑客。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM