Java 如何安排计时器每10个月运行一次?
如何安排计时器每10个月运行一次 事先非常感谢 我的实际方法是:Java 如何安排计时器每10个月运行一次?,java,timertask,Java,Timertask,如何安排计时器每10个月运行一次 事先非常感谢 我的实际方法是: @PostConstruct public void postConstruct() throws Exception { final TimerTask task = new TimerTask() { @Override public void run() {
@PostConstruct
public void postConstruct() throws Exception
{
final TimerTask task = new TimerTask()
{
@Override
public void run()
{
myprocess();
}
};
final Timer timer = new Timer();
final long delay = 0;
final long intevalPeriod = 20000;
// schedules the task to be run in an interval
timer.scheduleAtFixedRate(task, delay,
intevalPeriod);
}
如果您使用的是Spring,那么可以将注释与cron表达式一起使用。只需在bean类上注释任何公共方法,如下所示:
@Scheduled(cron = "0 0 0 10 * *")
public void myprocess() {
// perform task here
}
0 - at the zeroth second of the minute
0 - at the zeroth minute of the hour
0 - at the zeroth hour of the day
10 - on the 10th day of the month
* - any month
* - any day of the week
不要忘记在应用程序上下文中启用调度。如果您使用的是XML配置:
或者,如果您使用的是类:
@配置
@使能调度
公共类SpringConfig{
...
}
cron表达式0 10**分解如下:
@Scheduled(cron = "0 0 0 10 * *")
public void myprocess() {
// perform task here
}
0 - at the zeroth second of the minute
0 - at the zeroth minute of the hour
0 - at the zeroth hour of the day
10 - on the 10th day of the month
* - any month
* - any day of the week
Spring的cron表达式文档如下:
这里有一个链接,其中包含有关使用@Scheduled的更多信息:
以及Spring关于该主题的官方文件:
如果您使用的是Spring,则可以将注释与cron表达式一起使用。只需在bean类上注释任何公共方法,如下所示:
@Scheduled(cron = "0 0 0 10 * *")
public void myprocess() {
// perform task here
}
0 - at the zeroth second of the minute
0 - at the zeroth minute of the hour
0 - at the zeroth hour of the day
10 - on the 10th day of the month
* - any month
* - any day of the week
不要忘记在应用程序上下文中启用调度。如果您使用的是XML配置:
或者,如果您使用的是类:
@配置
@使能调度
公共类SpringConfig{
...
}
cron表达式0 10**分解如下:
@Scheduled(cron = "0 0 0 10 * *")
public void myprocess() {
// perform task here
}
0 - at the zeroth second of the minute
0 - at the zeroth minute of the hour
0 - at the zeroth hour of the day
10 - on the 10th day of the month
* - any month
* - any day of the week
Spring的cron表达式文档如下:
这里有一个链接,其中包含有关使用@Scheduled的更多信息:
以及Spring关于该主题的官方文件:
基于定时器的
如果您正在搜索一个坚持计时器概念的普通解决方案,那么您可以只计算正确的时间跨度,让任务在完成后,用正确的计算时间重新安排自己,以便下次执行
另见。将看起来像:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
public static ScheduledFuture<?> scheduleFor(Runnable runnable, ZonedDateTime when) {
Instant now = Instant.now();
// Use a different resolution if desired
long secondsUntil = ChronoUnit.SECONDS.between(now, when.toInstant());
return scheduler.schedule(runnable, secondsUntil, TimeUnit.of(ChronoUnit.SECONDS));
}
public static ZonedDateTime nextDate() {
return ZonedDateTime.now().plusMonths(1);
}
然后一开始像这样触发它
scheduleFor(task, ZonedDateTime.now().withDayOfMonth(10));
缺点
显然,这种解决方案,因为它是基于定时器的,有一个很大的缺点,它很容易漂移和不同步。例如,如果您的系统时间发生变化,或者任务的执行时间太长,以致于您进入第二天
后者可以通过在任务开始时而不是结束时生成下一个日期来轻松缓解
如果所有这些对你来说都不是一个因素,那么它很可能会按预期工作
否则,您可能应该采用另一种类似crontab的方法,定期检查日期,一旦日期匹配,它就会执行任务。与固定偏移量执行不同,如在中执行。。。秒。基于计时器
如果您正在搜索一个坚持计时器概念的普通解决方案,那么您可以只计算正确的时间跨度,让任务在完成后,用正确的计算时间重新安排自己,以便下次执行
另见。将看起来像:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
public static ScheduledFuture<?> scheduleFor(Runnable runnable, ZonedDateTime when) {
Instant now = Instant.now();
// Use a different resolution if desired
long secondsUntil = ChronoUnit.SECONDS.between(now, when.toInstant());
return scheduler.schedule(runnable, secondsUntil, TimeUnit.of(ChronoUnit.SECONDS));
}
public static ZonedDateTime nextDate() {
return ZonedDateTime.now().plusMonths(1);
}
然后一开始像这样触发它
scheduleFor(task, ZonedDateTime.now().withDayOfMonth(10));
缺点
显然,这种解决方案,因为它是基于定时器的,有一个很大的缺点,它很容易漂移和不同步。例如,如果您的系统时间发生变化,或者任务的执行时间太长,以致于您进入第二天
后者可以通过在任务开始时而不是结束时生成下一个日期来轻松缓解
如果所有这些对你来说都不是一个因素,那么它很可能会按预期工作
否则,您可能应该采用另一种类似crontab的方法,定期检查日期,一旦日期匹配,它就会执行任务。与固定偏移量执行不同,如在中执行。。。秒。对于这种持续时间,让操作系统运行计划的任务不是更好吗?@WJS我想说,在操作系统级别,有赞成和反对计划的理由。你可以使用这个。使用现代java.time API确定正确的日期很简单。让每个任务完成后,用动态计算的下一个日期重新安排自己。对于这种持续时间,让操作系统运行一个安排好的任务不是更好吗?@WJS我想说,在操作系统级别有赞成和反对安排它的论点。你可以用这个。使用现代java.time API确定正确的日期很简单。让每个任务完成后,用动态计算的下一个日期重新安排自己。这是惯用的方法。通过添加对cron表达式的解释,答案会变得更有用。@Zabuzard我已经删除了这句话。谢谢你是对的,我同意这种方法更可取。如果出于任何原因Spring不是一个选项,我会用你的方式。这是一种惯用的方式。通过添加对cron表达式的解释,答案会变得更有用。@Zabuzard我已经删除了这句话。谢谢你是对的,我同意这种方法更可取。无论出于什么原因,如果春天不是一个选择,我都会用你的方式。我倾向于使用一天中的特定时间,而不仅仅是ZoneDateTime.now。这将大大有助于解决漂移问题。我还将withDayOfMonth10包含在下一个日期中,以防漂移将我们推到下一个日历日。此外,我将调用scheduler.schedule放在finally块中,以便下一次调用
即使当前调用出现问题,也会被安排。我倾向于使用一天中的特定时间,而不仅仅是ZonedDateTime.now。这将大大有助于解决漂移问题。我还将withDayOfMonth10包含在nextDate中,以防漂移将我们推到下一个日历日。此外,我还将调用scheduler.schedule放在finally块中,这样即使当前调用出现问题,下一个调用也会得到调度。