首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ScheduledExecutorService每天晚上12点执行

ScheduledExecutorService每天晚上12点执行
EN

Stack Overflow用户
提问于 2017-04-21 07:42:00
回答 1查看 3.4K关注 0票数 6

我想每天早上12点开始ScheduledExecutorService,时间表必须在今天22/02/2017 :00:00 (UTC时间)开始,有人能告诉我我的代码是否正确吗?

代码语言:javascript
运行
复制
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
);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-21 08:23:45

tl;dr

代码语言:javascript
运行
复制
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的当前时区是所需的UTC。在调用日期-时间方法时,省略可选时区参数。这意味着JVM当前的默认时区在运行时被隐式和静默地应用。这种违约在任何时候都可能发生变化。JVM中任何应用程序线程中的任何代码都可以在运行时(!)更改默认值。

不隐式地依赖JVM当前的默认时区,而是总是显式地指定所需/期望的区域()。在你的情况下,我们要ZoneOffset.UTC。不要假设/希望部署JVM的当前缺省值设置为UTC,而停留在UTC,而是使用常量显式指定。

您似乎在使用优秀的http://www.joda.org/joda-time/库。该项目现在处于维护模式,团队建议迁移到java.time类。同样的基本概念,就像Joda-Time启发了java.time一样。

首先获取当前时刻,如在UTC中所看到的。

代码语言:javascript
运行
复制
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );

从中提取一个日期值。加一个明天的约会。

代码语言:javascript
运行
复制
LocalDate today = now.toLocalDate();
LocalDate tomorrow = today.plusDays( 1 );

“午夜”这个词可能是模棱两可和令人困惑。相反,要专注于“一天中的第一分钟”的概念。

我们的目标是推迟到你第一次执行你的遗嘱执行人服务的时间。所以我们需要从现在到明天的第一个时刻的时间跨度。

在确定一段时间时,当开头是包含的,而结尾是排他的时,则使用半开放方法。因此,我们的时间跨度从现在开始,一直持续到明天的第一个时刻,但不包括在内。

让java.time决定明天的第一个时刻。在世界协调时,一天总是在00:00开始。但在某些日期的时区却不是这样,在那里,一天可能在01:00这样的时间开始。所以,作为一种习惯,总是让java.time决定一天的第一分钟。OffsetDateTime tomorrowStart = OffsetDateTime.of(明天,LocalTime.MIN,ZoneOffset.UTC );

计算从现在到明天的第一个时刻的时间。Duration类表示与时间线无关的时间跨度。

代码语言:javascript
运行
复制
Duration d = Duration.between( now ,  tomorrowStart );
long millisUntilTomorrowStart = d.toMillis();

而不是一个神秘的数字文字,如86400000,使用自文档调用。

代码语言:javascript
运行
复制
TimeUnit.DAYS.toMillis( 1 )

因此,您的ScheduledExecutorService调用应该如下所示:

代码语言:javascript
运行
复制
….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.
)

对于整日递增,您不需要使用毫秒这样的细粒度。由于各种原因,执行者没有以完美的时间运行。所以我可能会在几分钟内计算出来。但不重要。

非常重要:--您需要将Runnable的run方法的代码封装在一个陷阱中,以防出现任何异常。如果有任何类型的异常到达执行者,执行者将静默停止。没有进一步的任务调度,也没有警告。搜索堆栈溢出,以获得更多信息,包括我的答案。

您不需要解释调用scheduleAtFixedRate的对象是什么。因此,这是代码的一个主要部分,除非您发布更多信息,否则我们无法帮助它。我担心你的名字叫“丝线”。该对象必须是ScheduledExecutorService的实现,而不是线程。

小贴士:避免在午夜时分跑步。许多事情往往在午夜发生在电脑上。例如,闰秒调整、许多Unix清理实用程序和常规活动(例如由天真的管理员安排的备份)。等五到十五分钟可能会避免麻烦和神秘的问题。

关于java.time

http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html框架内置到Java8和更高版本中。这些类取代了麻烦的旧遗赠日期时间类,如java.util.DateCalendarSimpleDateFormat

http://www.joda.org/joda-time/项目现在在维护模式中,建议迁移到java.time类。

要了解更多信息,请参见http://docs.oracle.com/javase/tutorial/datetime/TOC.html。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 4.2。不需要字符串,也不需要java.sql.*类。

在哪里获得java.time类?

  • Java 8Java 9,以及后来的
    • 内置的。
    • 带有捆绑实现的标准Java的一部分。
    • Java 9添加了一些次要的特性和修复。

  • Java 6Java 7
    • java.time的大部分功能都是在http://www.threeten.org/threetenbp/中移植到Java6&7中的。

三次-额外项目使用其他类扩展java.time。这个项目是将来可能加入java.time的试验场。您可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter更多

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43536761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档