Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Introduction

This article aims at introducing commonly used implementation of  Guava  Service  interface in version 13.0.1 with concrete examples from CDAP. This article contains material adapted or quoted from https://github.com/google/guava/wiki/ServiceExplained and Java docs in Guava source code, but citation is omitted for readability and convenience.

...

Guava  Service  interface represents an object with an operational state, with  start() and stop() methods that return a ListenableFuture that represents the result of an asynchronous transition to a desired state. Synchronous startAndWait() and stopAndWait() methods waits for the transition to a desired state to complete. For example, webservers, RPC servers, and timers,  can implement the  Service  interface.Managing the state of services like these, which require proper startup and shutdown management, can be nontrivial, especially if multiple threads or scheduling is involved. Guava provides some skeletons to manage the state logic and synchronization details for you.

...

  •  doStart()  doStart()  is called directly by the first call to  start() . The service is in Service.State.STARTING state when doStart()  method is called. doStart() should perform all initialization and then eventually MUST call  notifyStarted() to transition the service into Service.State.RUNNING state if start up succeeded or . startAndWait() will only return after notifyStarted() returns successfully. Any Throwable thrown by  doStart() will incur notifyFailed() to transition the service into Service.State.FAILED state. if start up failed.
  •  doStop()  doStop()  is called directly by the first call to  stop() only if the service in Service.State.RUNNING or  Service.State.STARTING state, which means doStart() must have completed successfully. Your Your doStop()  method method should shut down your service and then eventually call eventually MUST call notifyStopped()  if shutdown succeeded or startAndWait() will only return after notifyStarted() returns successfully. Any Throwable thrown by  doStop() will incur notifyFailed()  if shutdown failed. to transition the service into Service.State.FAILED state. 

start()  and  stop() methods of AbstractService run in the same thread in which they are called.  Your  doStart()  and  doStop() methods should be fast, because the service object is locked when doStart()  or  doStop() is running, and no other state transition can happen when the service object is locked. If you need to do expensive initialization, such as reading files, opening network connections, or any operation that might block, you should consider moving that work to another thread.

...

executor() returns the Executor that will be used to run this service. The default implementation returns a new Executor that sets the name of its threads to the string returned by getServiceName() method. Subclass may override this method to use a custom Executor.with a specific name, thread group or priority. startUp()  and  shutDown()  methods will be run in the Executor returned by executor()

 Unlike in AbstractExecutionThreadService, it's not guaranteed that startUp() has been called when shutDown() is called. 

To describe the execution schedule, you must implement the  scheduler()  method. Typically, you will use one of the provided schedules from  AbstractScheduledService.Scheduler , either  newFixedRateSchedule(initialDelay, delay, TimeUnit)  or  newFixedDelaySchedule(initialDelay, delay, TimeUnit) , corresponding to the familiar methods in  ScheduledExecutorService . Custom schedules can be implemented using  CustomScheduler ; see the Javadoc for details.

An example implementation of AbstractExecutionThreadService in CDAP is AbstractResourceReporter. It writes out resource metrics every reportInterval seconds which is defined in scheduler()

...