1
\$\begingroup\$

I've got a piece of code that will run a period task to do a small bit of processing. The task depends on an externally managed connection resource, and if the resource goes away then the task should unschedule itself.

Condensed into a unit test (although lacking any sort of assertions):

@Test
public void testSelfCancelling() throws InterruptedException {
  ScheduledThreadPoolExecutor refreshExecutor = new ScheduledThreadPoolExecutor(2);
  final AtomicReference<Future<?>> futureRef = new AtomicReference<>();

  final AtomicBoolean closed = new AtomicBoolean(false);

  futureRef.set(refreshExecutor.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
      // If the resource has been closed, then cancel this refresh task
      if (closed.get()) {
        Future<?> future = futureRef.get();
        // There may be a race condition here if the directory is closed after this task is scheduled, but before
        // the future is set. It's not a big deal because we will always cancel the task next time.
        if (future != null) {
          future.cancel(false);
        }
        System.out.println("Cancelling!");
      } else {
        System.out.println("Processing!");
      }
    }
  }, 1, 2, TimeUnit.SECONDS));

  refreshExecutor.schedule(new Runnable() {
    @Override
    public void run() {
      closed.set(true);
    }
  }, 6, TimeUnit.SECONDS);

  Thread.sleep(10000);
  refreshExecutor.shutdown();
}

As written, it works correctly. The test will be "processing" three times and then cancel. The whole execution wraps up at the 10 second mark as expected. However, is this safe? I have a nagging feeling that I'm missing some finer point of the concurrency which can lead to a deadlock or other undesirable situation down the road.

In my real use case, there would be multiple tasks, all checking separate resources, all potentially cancelling themselves independently.

\$\endgroup\$
  • \$\begingroup\$ If the resource becomes available again later - do you need a mechanism to re-enable execution? \$\endgroup\$ – Maxim Galushka Oct 31 '15 at 19:46
  • \$\begingroup\$ @Maxim - If the resource becomes available again, then it will be treated as a brand new resource and scheduled appropriately, yes. That part seems fairly straightforward and was elided from the review. \$\endgroup\$ – MikeD Nov 2 '15 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.