我想每天早上12点开始ScheduledExecutorService,时间表必须在今天22/02/2017 :00:00 (UTC时间)开始,有人能告诉我我的代码是否正确吗?
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
);
发布于 2017-04-21 08:23:45
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的当前时区是所需的UTC。在调用日期-时间方法时,省略可选时区参数。这意味着JVM当前的默认时区在运行时被隐式和静默地应用。这种违约在任何时候都可能发生变化。JVM中任何应用程序线程中的任何代码都可以在运行时(!)更改默认值。
不隐式地依赖JVM当前的默认时区,而是总是显式地指定所需/期望的区域()。在你的情况下,我们要ZoneOffset.UTC
。不要假设/希望部署JVM的当前缺省值设置为UTC,而停留在UTC,而是使用常量显式指定。
您似乎在使用优秀的http://www.joda.org/joda-time/库。该项目现在处于维护模式,团队建议迁移到java.time类。同样的基本概念,就像Joda-Time启发了java.time一样。
首先获取当前时刻,如在UTC中所看到的。
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );
从中提取一个日期值。加一个明天的约会。
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
类表示与时间线无关的时间跨度。
Duration d = Duration.between( now , tomorrowStart );
long millisUntilTomorrowStart = d.toMillis();
而不是一个神秘的数字文字,如86400000
,使用自文档调用。
TimeUnit.DAYS.toMillis( 1 )
因此,您的ScheduledExecutorService
调用应该如下所示:
….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.Date
、Calendar
和SimpleDateFormat
。
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.time。这个项目是将来可能加入java.time的试验场。您可以在这里找到一些有用的类,如Interval
、YearWeek
、YearQuarter
和更多。
https://stackoverflow.com/questions/43536761
复制相似问题