Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Schedule a single-threaded repeating runnable in java, but skip the current run if previous run is not finished

Tags:

java

Sometimes the duration of a repeated task is longer than its period (In my case, this can happen for hours at a time). Think of a repeated task that takes 7 minutes to run and is scheduled to run every 10 minutes, but sometimes takes 15 minutes for each run for a few hours in a row.

The Timer and ScheduledThreadPoolExecutor classes both have a scheduleAtFixedRate method that is usually used for this type of functionality. However, both have the characteristic that they 'try to catch up when they fall behind'. In other words, if a Timer falls behind by a few executions, it builds up a queue of work that will be worked on continuously until it catches back up to the number of runs that would have happened if none of the tasks had taken longer than the specified period. I want to avoid this behavior by skipping the current execution if the previous run is not complete.

I have one solution that involves messing around with the afterExecution method of a pooled executor, recalculating a delay, and rescheduling the runnable with the new delay, but was wondering if there's a simpler way, or if this functionality already exists in a common library somewhere. I know about scheduling with a fixed delay rather than a fixed period, but this will not work for me since it's important to try to execute the tasks at their fixed times. Are there any simpler options than my afterExecution solution?

like image 444
jonderry Avatar asked Aug 14 '12 01:08

jonderry


People also ask

How do I schedule a task at a specific time?

One of the methods the Timer class is void scheduleAtFixedRate(TimerTask task, Date firstTime, long period). This method schedules the specified task for repeated fixed-rate execution, beginning at the specified time.

How do you run a specific task everyday at a particular time using ScheduledExecutorService?

getSeconds(); ScheduledExecutorService scheduler = Executors. newScheduledThreadPool(1); scheduler. scheduleAtFixedRate(new MyRunnableTask(), initialDelay, TimeUnit. DAYS.

How do you stop a scheduled task in Java?

The cancel() method is used to cancel the timer task. The cancel() methods returns true when the task is scheduled for one-time execution and has not executed until now and returns false when the task was scheduled for one-time execution and has been executed already.

How do I stop scheduled executor service?

To properly shut down an ExecutorService, we have the shutdown() and shutdownNow() APIs. This method returns a list of tasks that are waiting to be processed.


2 Answers

I think what you want is for the long-running task itself to not run in the ScheduledExecutorService itself, but in a background thread. Then the fixed-rate task will always complete quickly, since it is only used for checking whether to start the actual task in the background (or not, if it's still running from last time).

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
final Runnable actualTask = null;

executorService.scheduleAtFixedRate(new Runnable() {
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private Future<?> lastExecution;
    @Override
    public void run() {
        if (lastExecution != null && !lastExecution.isDone()) {
            return;
        }
        lastExecution = executor.submit(actualTask);
    }
}, 10, 10, TimeUnit.MINUTES);
like image 65
Mark Peters Avatar answered Oct 18 '22 18:10

Mark Peters


You could use scheduleWithFixedDelay method instead. It's similar but this one does not have a queue for missed runs and instead starts counting again only when the current Runnable was terminated.

The documentation states the reexecution of the Runnable will be scheduled based on the delay parameter:

The delay between the termination of one execution and the commencement of the next.

like image 21
DanielCuadra Avatar answered Oct 18 '22 17:10

DanielCuadra