ScheduledExecutorService with variable delay

parkr picture parkr · Oct 5, 2009 · Viewed 15.7k times · Source

Suppose I have a task that is pulling elements from a java.util.concurrent.BlockingQueue and processing them.

public void scheduleTask(int delay, TimeUnit timeUnit)
{
    scheduledExecutorService.scheduleWithFixedDelay(new Task(queue), 0, delay, timeUnit);
}

How can I schedule / reschedule the task if the frequency can be changed dynamically?

  • The idea is to take a stream of data updates and propagate them in batch to a GUI
  • The user should be able to vary the frequency of updates

Answer

Adamski picture Adamski · Oct 5, 2009

Use schedule(Callable<V>, long, TimeUnit) rather than scheduleAtFixedRate or scheduleWithFixedDelay. Then ensure that your Callable reschedules itself or a new Callable instance at some point in the future. For example:

// Create Callable instance to schedule.
Callable<Void> c = new Callable<Void>() {
  public Void call() {
   try { 
     // Do work.
   } finally {
     // Reschedule in new Callable, typically with a delay based on the result
     // of this Callable.  In this example the Callable is stateless so we
     // simply reschedule passing a reference to this.
     service.schedule(this, 5000L, TimeUnit.MILLISECONDS);
   }  
   return null;
  }
}

service.schedule(c);

This approach avoids the need to shut down and recreate the ScheduledExecutorService.