2012-04-18 51 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); 
}