views:

343

answers:

3

I have a web application that synchronizes with a central database four times per hour. The process usually takes 2 minutes. I would like to run this process as a thread at X:55, X:10, X:25, and X:40 so that the users knows that at X:00, X:15, X:30, and X:45 they have a clean copy of the database. It is just about managing expectations. I have gone through the executor in java.util.concurrent but the scheduling is done with the scheduleAtFixedRate which I believe provides no guarantee about when this is actually run in terms of the hours. I could use a first delay to launch the Runnable so that the first one is close to the launch time and schedule for every 15 minutes but it seems that this would probably diverge in time. Is there an easier way to schedule the thread to run 5 minutes before every quarter hour?

A: 

TimerTask handles this case.

See schedule(TimerTask, Date)

If you don't want to have to keep scheduling the jobs, you may want to look into a job scheduling tool like Quartz.

danben
+2  A: 

Quartz would be a good fit since you're application is web-based. It will provide the fine-grained time based scheduling you need.

Quartz is a full-featured, open source job scheduling service that can be integrated with, or used along side virtually any Java EE or Java SE application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may executed virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as JTA transactions and clustering.

Taylor Leese
+2  A: 

You can let the Runnable schedule its "next run".

Such as,

class Task implements Runnable {
    private final ScheduledExecutorService service;

    public Task(ScheduledExecutorService service){
        this.service = service;
    }

    public void run(){
        try{
             //do stuff
        }finally{
            //Prevent this task from stalling due to RuntimeExceptions.
            long untilNextInvocation = //calculate how many ms to next launch
            service.schedule(new Task(service),untilNextInvocation,TimeUnit.MILLISECONDS);
        }
    }
}
Enno Shioji
This looks great... will give it a try.
rmarimon
Dit it this way and is working beautifully. Thanks.
rmarimon
@rmarimon: NP :) Just be careful that a `RuntimeException` can stop the periodic execution. I got burned by this, so I edited the answer accordingly.
Enno Shioji
I just changed it. I had it like try { } catch (Exception e) { } and then the reschedule. But the finally seems like the right approach.
rmarimon