11

I have a server side application where clients can request to reload the configuration. If a client request to reload the configuration, this should not be done immediately, but with an delay of 1 minute. If another client also requests to reload the configuration in the same minute, this request should be ignored.

My idea is to schedule a task with a ScheduledExecutorService like:

 ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
 service.schedule(new LoadConfigurationTask(), 1, TimeUnit.MINUTES);

 public class LoadConfigurationTask Runnable {
    public void run() {
      // LoadConfiguration
    }
 }

How can I check if a LoadConfigurationTask has been scheduled, but not executed yet, to be able to ignore further requests until the configuration is reloaded ?

markus
  • 6,258
  • 13
  • 41
  • 68

2 Answers2

41

You can simply get a reference to a ScheduledFuture like this:

ScheduledFuture<?> schedFuture = service.schedule(new LoadConfigurationTask(), 1, TimeUnit.MINUTES);

Now with the future, you can check if the task is done:

schedFuture.isDone();

Or even better, check how much time left before the execution will begin:

schedFuture.getDelay(TimeUnit.MINUTES);

There is no need for external variable to track the state.

sam.bishop
  • 388
  • 3
  • 14
Minh-Triet LÊ
  • 1,374
  • 9
  • 17
  • Note this may not return exactly what you want. For example, I created a task that runs for 1 minute. Called `future.cancel()` within the first 10 seconds. The future returns `true` for `isDone() and isCancel()` however the task continues running until it finishes its 1 minute. – user3758745 Mar 29 '19 at 16:03
  • @user3758745 You have pointed out an important point, which is related to the way Java handle threads. Once the work begins, there is almost no way to stop it from inside the JVM. Call future.cancel(true) will send a interrupt signal but only if the thread is coded to handle interrupt signal properly. Feel free to check the answer https://stackoverflow.com/questions/3976344/handling-interruptedexception-in-java – Minh-Triet LÊ Jun 20 '19 at 08:23
  • If you cancel a task with ScheduledFuture.cancel(false) and it is long-running, then SchedFuture.isDone() will be true, but in reality the task continues to run. Probably the best way is that quoted by "Tim B". – MhagnumDw Jun 04 '20 at 15:37
4

The easiest way is just to set an AtomicBoolean http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html

Set it to true when you launch the task, set it to false when the task finishes, don't launch any more unless it is on false.

Make sure you do the setting to false in a finally block so you can't accidentally exit without un-setting it.

Tim B
  • 40,716
  • 16
  • 83
  • 128