Reputation: 2297
I'm developing a service that suppose to start of every hour repeating exactly on the hour (1:00PM, 2:00PM, 3:00PM, etc.).
I tried following but it has one problem that for first time i have to run the program exactly at start of hour and then this scheduler will repeat it.
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleWithFixedDelay(new MyTask(), 0, 1, TimeUnit.HOURS);
Any suggestion to repeat my task regardless when i run the program?
Regards, Imran
Upvotes: 15
Views: 19567
Reputation: 41
If you are developing an Java EE application, not necessarily using Spring (as indicated in @deepmoteria's answer), you can also use the @Schedule annotation.
Upvotes: 0
Reputation: 13696
The millisToNextHour
method in krishnakumarp's answer can be made more compact and straightforward in Java 8, which would result in the following code:
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);
}
Upvotes: 10
Reputation: 9295
I would also suggest Quartz for this. But the above code can be made to run first at the start of the hour using the initialDelay parameter.
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;
}
Upvotes: 17
Reputation: 2441
If you are using the spring in your service than you can directly use the annotation based scheduler @Schedule annotation which takes cron expression as a parameter or the delay in milliseconds, just add this annotation above the method you want to execute and this method will be executed. Enjoy...........
Upvotes: 2
Reputation: 18631
If you can afford to use an external library, then Quartz provides very flexible and easy to use scheduling modes. For example cron
mode should be perfect for your case. Below a simple example of scheduling a certain Job to be executed every hour:
quartzScheduler.scheduleJob(
myJob, newTrigger().withIdentity("myJob", "group")
.withSchedule(cronSchedule("0 * * * * ?")).build());
Have a look at the tutorial and examples to find which formulations suits your tastes. They also show how to deal with errors.
Upvotes: 7