2012-04-18 49 views
10

我正在开发一种服务,假设每小时开始时刻(1:00 PM,2:00 PM,3:00 PM等)重复一次。如何计划每小时开始的任务

我试过,但它有一个问题,第一次我必须在小时开始时正好运行程序,然后这个调度程序会重复它。

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 
scheduler.scheduleWithFixedDelay(new MyTask(), 0, 1, TimeUnit.HOURS); 

任何建议重复我的任务,无论我什么时候运行程序?

问候, 伊姆兰

回答

10

我也建议Quartz为此。但是可以使用initialDelay参数在上个小时的开始时间运行上面的代码。

Calendar calendar = Calendar.getInstance(); 
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 
scheduler.scheduleAtFixedRate(new MyTask(), millisToNextHour(calendar), 60*60*1000, TimeUnit.MILLISECONDS); 



private static long millisToNextHour(Calendar calendar) { 
    int minutes = calendar.get(Calendar.MINUTE); 
    int seconds = calendar.get(Calendar.SECOND); 
    int millis = calendar.get(Calendar.MILLISECOND); 
    int minutesToNextHour = 60 - minutes; 
    int secondsToNextHour = 60 - seconds; 
    int millisToNextHour = 1000 - millis; 
    return minutesToNextHour*60*1000 + secondsToNextHour*1000 + millisToNextHour; 
} 
+1

我们将使用scheduleWithFixedDelay或scheduleAtFixedDelay?我想我们会用scheduleAtFixedDelay。否则会增加重复执行时间。 – ImranRazaKhan 2012-04-18 08:13:06

+2

是的。在你的情况下,你应该使用scheduleAtFixedRate。更新了答案 – krishnakumarp 2012-04-18 08:22:35

7

如果你能负担得起使用一个外部库,然后Quartz提供了非常灵活和易于使用的调度方式。例如cron模式应该适合您的情况。下面每隔一小时要执行调度一定Job的一个简单的例子:

quartzScheduler.scheduleJob(
    myJob, newTrigger().withIdentity("myJob", "group") 
         .withSchedule(cronSchedule("0 * * * * ?")).build()); 

看一看在tutorialexamples找到其配方适合你的口味。他们还展示了如何处理错误。

1

如果您在服务中使用spring,那么您可以直接使用基于注释的计划程序@Schedule注释,该注释将cron表达式作为参数或以毫秒为单位的延迟,只需将此注释添加到要执行的方法上方即可这个方法将被执行。享受...........

5

millisToNextHour方法krishnakumarp的answer可以在Java 8更加紧凑和简单,这将导致下面的代码:

public void schedule() { 
    ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(); 
    scheduledExecutor.scheduleAtFixedRate(new MyTask(), millisToNextHour(), 60*60*1000, TimeUnit.MILLISECONDS); 
} 

private long millisToNextHour() { 
    LocalDateTime nextHour = LocalDateTime.now().plusHours(1).truncatedTo(ChronoUnit.HOURS); 
    return LocalDateTime.now().until(nextHour, ChronoUnit.MILLIS); 
}