ScheduledExecutorService每天晚上12点UTC时间执行 [英] ScheduledExecutorService execute every night at 12 AM UTC Time

查看:225
本文介绍了ScheduledExecutorService每天晚上12点UTC时间执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想每天正好在凌晨12点启动ScheduledExecutorService,计划必须从今天的22/02/2017 00:00:00(UTC TIME)开始,有人可以告诉我我的代码是否正确?

I want to start ScheduledExecutorService exactly 12 AM daily ,Schedule has to Start at today at 22/02/2017 00:00:00 (UTC TIME),Can any one tell me Whether my code is Correct or not?

DateTime today = new DateTime().withTimeAtStartOfDay(); 
DateTime startOfTommorrow = today.plusDays(1).withTimeAtStartOfDay();

Long midnight = startOfTommorrow.getMillis();
long midnights = (midnight / 1000)  / 60;
final DateFormat nextDateTymFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println("***********************************");
System.out.println("Schedule Updater "+nextDateTymFormat.format(new Date()));
System.out.println("today "+today);
System.out.println("startOfTommorrow "+startOfTommorrow);
System.out.println("midnight Long "+midnight);
System.out.println("***********************************");
vitalScheduleThread.scheduleAtFixedRate(new Runnable() {

    @Override
    public void run() {

        System.out.println("Hello vitalSchService !!"+nextDateTymFormat.format(new Date()));

        Thread.currentThread().setName("vitalSchService");

        //sendMail();
        vitalSchedule.process(springContext);
    }
}, midnight , 86400000 , TimeUnit.MILLISECONDS
);

推荐答案

tl; dr

OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC ) ;  // Capture the current moment.

….scheduleAtFixedRate(
    new Runnable() { … } ,           // Define task to be executed as a `Runnable`.
    Duration.between(                // Determine amount of time for initial delay until first execution of our Runnable.
        now ,                        // Current moment.
        now.toLocalDate().plusDays( 1 ).atStartOfDay( ZoneOffset.UTC )  // Determine the first moment of tomorrow in our target time zone (UTC). Used as the exclusive end of our Half-Open span of time.
    ) ,
    TimeUnit.DAYS.toMillis( 1 ) ,    // Amount of time between subsequent executions of our Runnable. Use self-documenting code rather than a "magic number" such as `86400000`. 
    TimeUnit.MILLISECONDS            // Specify the granularity of time used in previous pair of arguments.
)                                    // Returns a `ScheduledFuture` which you may want to cache.

详细信息

明确指定区域

您假设JVM当前的时区是您想要的

Details

Specify zone explicitly

You are assuming the JVM’s current time zone is your desired UTC. You omit the optional time zone argument when calling the date-time methods. That omission means the JVM’s current default time zone is applied implicitly and silently at runtime. That default may change at any moment. Any code in any thread of any app within that JVM can change the default during runtime(!).

始终明确地指定所需/期望的区域,而不是隐式依赖JVM的当前默认时区.对于您的情况,我们希望 ZoneOffset.UTC .无需假设/希望部署JVM的当前默认值设置为UTC并保持在UTC,而是使用

Instead of relying implicitly on the JVM’s current default time zone, always specify your desired/expected zone explicitly. In your case, we want ZoneOffset.UTC. Instead of assuming/hoping the deployment JVM’s current default is set to UTC, and stays at UTC, specify explicitly using the constant.

您似乎在使用出色的 Joda-Time 图书馆.该项目现在处于维护模式,团队建议迁移到java.time类.与 Joda-Time 启发 java.time 的基本概念相同.

You seem to be using the excellent Joda-Time library. That project is now in maintenance mode, with the team advising migration to the java.time classes. Same basic concepts, as Joda-Time inspired java.time.

首先获取当前时刻,如 UTC 所示.

First get the current moment as seen in UTC.

OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );

从中提取仅日期的值.添加一个即可获取明天的日期.

Extract a date-only value from that. Add one to get tomorrow’s date.

LocalDate today = now.toLocalDate();
LocalDate tomorrow = today.plusDays( 1 );

午夜"一词可能含糊不清且令人困惑.相反,请关注一天中的第一时刻"的概念.

The term "midnight" can be ambiguous and confusing. Instead, focus on the concept of "first moment of the day".

我们的目标是将时间延迟到您第一次执行遗嘱执行人服务之前.因此,我们需要从现在到明天第一天之间的时间跨度.

We are aiming for the amount of time to delay until your first execution of your executor service. So we need the span of time between now and the first moment of tomorrow.

在确定时间跨度时,当开始为包含且结束为排他时,请使用Half-Open方法.因此,我们的时间跨度从现在(当前时刻)开始,一直到明天的第一时刻,但不包括在内.

And when determining a span of time, use the Half-Open method when the beginning is inclusive while the ending is exclusive. So our span of time starts with now (the current moment) and runs up to, but does not include) the first moment of tomorrow.

让java.time确定明天的第一天.在UTC中,日期总是从00:00开始.但是在某些日期的某些时区中并非如此,一天的开始时间可能是01:00.因此,作为一种习惯,请始终让java.time确定一天的第一时刻.OffsetDateTime明天开始= OffsetDateTime.of(明天,LocalTime.MIN,ZoneOffset.UTC);

Let java.time determine the first moment of the day tomorrow. In UTC the day always starts at 00:00. But not so in some time zones on some dates, where the day might start at a time like 01:00. So, as a habit, always let java.time determine first moment of the day. OffsetDateTime tomorrowStart = OffsetDateTime.of( tomorrow , LocalTime.MIN , ZoneOffset.UTC );

计算从现在到明天第一天之间的经过时间. Duration 类表示未附加到时间轴的时间跨度.

Calculate the elapsed time between now and that first moment of tomorrow. The Duration class represents such spans of time unattached to the timeline.

Duration d = Duration.between( now ,  tomorrowStart );
long millisUntilTomorrowStart = d.toMillis();

请使用自记录调用,而不是像 86400000 这样的神秘数字文字.

Instead of a mysterious number literal such as 86400000, use a self-documenting call.

TimeUnit.DAYS.toMillis( 1 )

因此,您的 ScheduledExecutorService 调用看起来像这样:

So your ScheduledExecutorService call would look like this:

….scheduleAtFixedRate(
    new Runnable() { … } ,          // Task to be executed repeatedly, defined as a Runnable.
    millisUntilTomorrowStart ,      // Initial delay, before first execution. Use this to get close to first moment of tomorrow in UTC per our code above.
    TimeUnit.DAYS.toMillis( 1 ) ,   // Amount of time in each interval, between subsequent executions of our Runnable.
    TimeUnit.MILLISECONDS           // Unit of time intended by the numbers in previous two arguments.
)

要整天增加,您不必使用毫秒数这样的精细粒度.由于各种原因,执行者的时机都不理想.因此,我可能会在几分钟内完成计算.但并不重要.

For incrementing in whole days, you needn't use such a fine granularity as milliseconds. The executors do not run with perfect timing for various reasons. So I probably would have calculated in minutes. But not important.

非常重要::对于任何异常,您都需要将Runnable的 run 方法的代码括在陷阱中.如果要到达执行程序的任何类型的异常,执行程序都将默默地停止.没有进一步的任务计划,也没有警告.搜索堆栈溢出以获取更多信息,包括我的答案.

Very important: You need to enclose the code of your Runnable’s run method in a trap for any exception. If an Exception of any type were to reach the executor, the executor silently halts. No further scheduling of tasks, and no warning. Search Stack Overflow for more info including an Answer by me.

您没有解释调用什么对象 ScheduledExecutorService 的实现,而不是线程.

You do not explain what is the object on which you call scheduleAtFixedRate. So that is a major part of the code that we cannot help with until you post more info. I'm concerned you have it named "Thread". That object must be an implementation of ScheduledExecutorService, not a thread.

提示:避免在午夜准时跑步.午夜计算机上往往会发生许多事情.例如,leap秒调整,许多Unix清理实用程序以及日常活动(例如,可能由天真的管理员安排的备份).等待大约五到十五分钟可以避免麻烦和神秘的问题.

Tip: Avoid running things at exactly midnight. Many things tend to happen on computers at midnight. For example, leap second adjustments, many Unix cleanup utilities, and routine activities such as backups that may have been scheduled by naïve administrators. Waiting something like five or fifteen minutes may avoid hassles and mysterious problems.

java.time 框架内置于Java 8及更高版本中.这些类取代了麻烦的旧版日期时间类,例如 Calendar ,& SimpleDateFormat

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time 项目,现在位于<一个href ="https://en.wikipedia.org/wiki/Maintenance_mode" rel ="nofollow noreferrer">维护模式,建议迁移到要了解更多信息,请参见 Oracle教程.并在Stack Overflow中搜索许多示例和说明.规范为 JSR 310 .

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

您可以直接与数据库交换 java.time 对象.使用符合 JDBC驱动程序/jeps/170"rel =" nofollow noreferrer> JDBC 4.2 或更高版本.不需要字符串,不需要 java.sql.* 类.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

在哪里获取java.time类?

Where to obtain the java.time classes?

  • Java SE 8 Java SE 9 和更高版本
    • 内置.
    • 具有捆绑的实现的标准Java API的一部分.
    • Java 9添加了一些次要功能和修复.
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

    > ThreeTen-Extra 项目扩展了java.time与其他班级.该项目为将来可能在java.time中添加内容提供了一个试验场.您可能会在这里找到一些有用的类,例如 间隔 年周" YearQuarter 更多

    这篇关于ScheduledExecutorService每天晚上12点UTC时间执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆