Reinitialize fix delay in ScheduledExecutorService

10,218

Solution 1

You need to keep the reference of the returned ScheduledFuture<?> object:

ScheduledFuture<?> handle =
       scheduler.scheduleWithFixedDelay(runnable, 0, 5, TimeUnit.SECONDS);

With this reference you cancel the current task and create another one with the new delay:

handle.cancel(false);    
handle = scheduler.scheduleWithFixedDelay(runnable, 0, 60, TimeUnit.SECONDS);

Here is an example:

public class Test5 {
    static int i = 0;
    static ScheduledExecutorService executor;
    static Runnable runnable;
    static ScheduledFuture<?> future;

    public static void main(String args[]) throws InterruptedException{
        executor = Executors.newScheduledThreadPool(1);
        runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Inside runnable" + i++);
            }
        };
        future = executor.scheduleWithFixedDelay(runnable, 0, 5, TimeUnit.SECONDS);

        Thread.sleep(20000l);

        changeDelay();
    }

    public static void changeDelay() {
        boolean res = future.cancel(false);

        System.out.println("Previous task canceled: " + res);

        future = executor.scheduleWithFixedDelay(runnable, 0, 20, TimeUnit.SECONDS);
    }
}

Solution 2

As I see ScheduledExecutorService.scheduleWithFixedDelay(runnable, initDelay , delay, TimeUnit.SECONDS) returns ScheduledFuture which doesn't have a method setDelay(delay) which will allow it to change the delay once created.

The best option would be to cancel the current runnable ScheduledFuture.cancel(false) and start a new scheduled task with the help of scheduleWithFixedDelay using new delay value.

DO NOT CALL changeDelay from run method. Instead call it from main method itself like below

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorExample {
    static int i = 0;
    static ScheduledExecutorService executor;
    static Runnable runnable;
    static ScheduledFuture<?> future;

    public static void main(String args[]) {
        executor = Executors.newScheduledThreadPool(1);
        runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Inside runnable" + i++);
            }
        };
        future = executor.scheduleWithFixedDelay(runnable, 0, 2, TimeUnit.SECONDS);
        try {
            Thread.sleep(4000); //sleeping for 2 seconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        changeDelay();
    }

    public static void changeDelay() {
        future.cancel(false);
        future = executor.scheduleWithFixedDelay(runnable, 0, 10, TimeUnit.SECONDS);
    }
}

You see that after a while the delay changes to 10 seconds from 2 seconds

Share:
10,218
Souvik
Author by

Souvik

Updated on July 18, 2022

Comments

  • Souvik
    Souvik almost 2 years

    As per my requirement, I have to execute some particular code after certain period of time. To do the same I have chose ScheduledExecutorService.scheduleWithFixedDelay(runnable, 0, 5, TimeUnit.SECONDS) and it's working fine for me. But according to my another requirement, the time mentioned in fixedDelay should be configurable at runtime. Means, currently total Delay is 5 seconds but latter if user want then can change the time into 60 seconds and in runtime fixedDelay will run after 60 seconds. Any help would be appreciable.

    Please see the code:

    static int i = 0;
        static ScheduledExecutorService executor;
        static Runnable runnable;
        static ScheduledFuture<?> future;
    
        public static void main(String args[]) {
            executor = Executors
                    .newScheduledThreadPool(1);
            runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("Inside runnable" + i++);
                    changeDelay();
                }
            };
            future =
                    executor.scheduleWithFixedDelay(runnable, 0, 5, TimeUnit.SECONDS);
    
        }
    
        public static void changeDelay() {
            future.cancel(false);
            future = executor.scheduleWithFixedDelay(runnable, 0, 10, TimeUnit.SECONDS);
        }
    

    Here I have used changeDelay method to change the delay time. But it's not working.

  • Rahul Hawge
    Rahul Hawge about 7 years
    How do i change the timing back and forth depending on a condition? Currently once i changed the scheduled time, I am not able to reschedule it