I'd like to create a method that delays the execution on method invocation by 60s.
Problem: if the method is called within that 60s, I want it to be delayed again by 60s from last point of invocation. If then not called within 60s, the execution may continue.
I started as follows, but of course this is only a one-time delay:
public void sendDelayed(String info) {
//TODO create a task is delayed by 60s for each method invocation
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.schedule(Classname::someTask, 60, TimeUnit.SECONDS);
}
How could I further delay the execution on each invocation?
CodePudding user response:
executorService.schedule
returns a ScheduledFuture
which provides a cancel
method to cancel its execution. cancel
takes a single boolean parameter mayInterruptIfRunning
which, when set to false
, will only cancel the execution if the task has not started yet. See also the docs.
Using this you could do something like this:
private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> future;
public void sendDelayed(String info) {
// When there is a task that has not been started yet, stop it:
if (future != null) {
boolean cancelled = future.cancel(false);
if (cancelled) {
logger.debug("Task has been cancelled before execution");
} else {
logger.debug("Task is already running or has been completed");
}
}
// Old task has been cancelled or already started - schedule a new task
future = executorService.schedule(Classname::someTask, 60, TimeUnit.SECONDS);
}
You may have to take care of avoiding race conditions regarding concurrent access to the future
field though.