4

I am using an AbstractScheduledService with a scheduler. A simple pattern like:

class MyService extends AbstractScheduledService {

   // KEEP THIS VAR IN MIND W.R.T the SHUTDOWN_HOOK BELOW
   public static volatile boolean keepRunning = true;

   protected void startUp() throws Exception {
     // startup stuff
   }

   protected void runOneIteration() throws Exception {
     // main logic stuff
   }

   protected void shutDown() throws Exception {
     // shutdown stuff
   }

   protected Scheduler scheduler() {
     return Scheduler.newFixedRateSchedule(0, 1, TimeUnit.SECONDS);
   }
 }

Now, I want to implement a typical shutdown hook like this: (the below snippet will be in main method)

final Thread mainThread = Thread.currentThread();
        LOGGER.debug("Adding the shutdown hook");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                keepRunning = false;
                LOGGER.debug("The shutdown hook was engaged. Setting keepRunnning to false.");
                try {
                     // Is this appropriate?
                     mainThread.join();
                } catch (InterruptedException e) {
                    // handle exception here
                }
            }
        });

The shutdown hook is from typical docs example. It doesn't seem to work well with the Guava services pattern since the service itself is running on a different thread.

My service has a polling loop in the runOneIteration() logic. I want it to complete it's current task at hand and then shutdown gracefully when is sees that the keepRunning is now false since the Shutdown hook was engaged some time in the recent past when it was busy with its current iteration.

Any ideas how this can be done gracefully (complete current iteration and then shutdown)?

Urjit
  • 1,150
  • 8
  • 15

1 Answers1

6

Wouldn't you just call stopAndWait()?

Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            service.stopAsync().awaitTerminated(60, TimeUnit.SECONDS);
        }
});
rynop
  • 50,086
  • 26
  • 101
  • 112
Christofer
  • 61
  • 1
  • I tried that but it stops the service right in the middle of whatever it was doing. I want it to be able to complete its current iteration/task and then exit. – Urjit Aug 31 '12 at 16:21
  • 2
    @Urjit The AbstractScheduledService can stop between any call of runOneIteration but not during a call (that is impossible). If you don't want the service to be able to be stopped between iterations maybe you would be better off using AbstractExecutionThreadService and coding the loop yourself. – luke Sep 04 '12 at 15:41
  • Thanks @luke. I never realized that its impossible to stop between calls of runOneIteration. I did want to stop even in between calls and the volatile boolean keepRunning worked out fine with the stopAndWait except that there is no need for the mainThread.join anyways since the service runs on its own thread pool. – Urjit Sep 06 '12 at 16:35
  • @Urjit I think you read what i wrote backwards, being able to stop gracefully (i.e. without interrupting threads) is the entire point of AbstractScheduledService. Maybe this would be clearer if you showed your implementation of runOneIteration (do you have a polling loop in runOneIteration?) – luke Sep 06 '12 at 20:35
  • The ShutdownHook is not guaranteed to finish. – Costi Muraru Jan 15 '18 at 14:36