Overview
The guava interface represents an object that has a running state, with methods for starting and stopping. such as network servers, RPC servers, and timers, etc., can implement the service interface. The state of being in charge of services like this requires proper management of startup and shutdown, so it can be cumbersome, especially when it comes to multithreading and scheduling. Guava provides a basic skeleton that can help you manage the state logic, as well as the details of the synchronization
The usual life cycle of a service is
Service.State.NEW
To
Service.State.STARTING
To
Service.State.RUNNING
To
Service.State.STOPPING
To
Service.State.TERMINATED
A Service that has been stopped cannot be restarted. If the service fails when it starts or runs and stops, it goes into Service.State.FAILED
state.
A service can be used startAsync()
to start asynchronously, and this method returns the ' this ' reference to make it easy to use the method chain. Only this service NEW
can be called when it is in a state. So, your program should have a unique place to start every service.
Stopping a service is similar to using an async stopAsync()
method. But unlike startAsync()
methods, it can be safely called multiple times. This allows it to deal with competing issues that may be encountered in shutting down the server.
The service also provides several ways to wait for the completion of a service state transition.
- To use asynchronously
addListener()
. AddListener () allows you to add one Service.Listener
, which will be called when the service state transitions for services. It is important to note that if the listener is added, the server is not already in NEW
a state. , then the state transitions that have occurred are not replayed on this listener.
- To use asynchronously
awaitRunning()
. It is non-interruptible (uniterruptible), does not throw a checked exception, and is returned when the service is started. If the service fails to start, a illegalstateexception is thrown. Similarly awaitTerminated()
, it is called to wait for the service to reach the terminating state ( TERMINATED
or FAILED
). Both methods have overloaded methods that allow you to specify a time-out.
Service
the interface is subtle. We do not recommend implementing it directly. You can use one of the several virtual classes that we provide in guava as the basis for your implementation. Each base class provides a specific threading model.
Implement Abstractidleservice
The AbstractIdleService
skeleton implements a service that does not need to perform any action in the "running" state, so it does not need a thread at run time, but it still needs to perform the start and stop actions. Implementing such a service requires only inheriting Abstractidleservice, and implementing startUp()
and shutDown()
methods,
protected void startUp () { servlets.add (new Gcstatsservlet ());} protected void ShutDown () {}
It should be noted that any query to Gcstatsservlet is already running in one thread. Therefore, when this service is running, we do not need it to perform task operations.
Abstractexecutionthreadservice
One AbstractExecutionThreadService
executes the start, move, and close operations in the same thread. You must override the run()
method, and the method must respond to closing the request. For example, you might perform these actions in a work cycle:
Public void run () { while (isrunning ()) { // perform a unitof work c12/>}}
Alternatively, you can override triggerShutdown()
The method as long as it enables the run () method to return. Overwriting the startUp () and shutdown () methods is optional, but the status of the service is managed by the skeleton for you.
protected void StartUp () {dispatcher.listenforconnections (port, queue);} protected void run () {Connection Connection; while ((connection = Queue.take ()!= POISON)) {process (connection); }} protected void Triggershutdown () {dispatcher.stoplisteningforconnections (queue); Queue.put (POISON);}
It is important to note that start () calls your startUp () method, creates a thread for you, and calls the run () method in this thread. The Stop () method calls the Triggershutdown () method and waits for the thread to stop. The point is that the run () method is not executed in the thread that called start ().
Abstractscheduledservice
A AbstractScheduledService
task that performs some periodic tasks while it is moving. Its subclass overrides runOneIteration()
to specify tasks for each cycle, and it also needs to overwrite the startUp and shutDown()
methods we are familiar with
In order to describe how to dispatch execution, you need to implement the scheduler()
method. In general, you will use one of the several schedulers that you have already AbstractScheduledService.Scheduler
provided, or it is similar to the newFixedRateSchedule(initialDelay, delay, TimeUnit)
newFixedDelaySchedule(initialDelay, delay, TimeUnit)
method in the Scheduledexecutorservice that we are familiar with. The custom scheduler can be used for implementation, see Javadoc.
Abstractservice
If you need to manage threads yourself, you need to overwrite them directly AbstractService
. In general, the above mentioned implementations are sufficient, but, in some cases, it is recommended to implement Abstractservice , for example, you have your own line semantics things to model, make it a Service, You will have your own special thread-related requirements.
In order to implement Abstractservice, you need to implement these two methods
doStart()
: Dostart () is called directly at the first call to Startasync ( ), and your Dostart () method should complete all initialization work and be called when it succeeds, or when it fails to start.
doStop()
: Dostop () is called at the first call to Stopasync () , and your dostop () method should shut down your service and call if the shutdown succeeds, the final call is made, notifyStopped()
or the shutdown fails notifyFailed()
.
Your dostart and dostop methods should be executed very quickly. If you need to do expensive initialization work, such as reading files, turning on network connections, or doing any work that might block, you need to move those jobs to another thread.
Using Serivcemanager
In addition to the skeleton implementation of the service , Guava also provides a ServiceManager
class that makes it easier to operate on operations that are related to multiple service implementations. Creates a new ServiceManagerusing the collection of service . Then you can manage them:
startAsync()
All managed services will be started. Just like Service#startAsync()
, you can only NEW
call this method once when all the services are
stopAsync()
All managed services will be stopped
addListener
Will be added ServiceManager.Listener
, it will be called when all major state transitions are
awaitHealthy()
Will wait for all services to reach RUNNING status
awaitStopped()
Will wait for all services to arrive at the terminating state.
Or check these services:
isHealthy()
Returns true when all services are in a state
- will return a consistent snapshot for all services, indexed by their state.
startupTimes()
will return the map from the managed Service to the number of milliseconds it took to start. Guava guarantees that the returned map will be sorted by startup time (startup times).
We suggest that the lifecycle of a service is managed through ServiceManager , but state transitions through other mechanisms do not affect the correctness of its methods. For example, if some services are not started by Startasync () , the listener will still be invoked at the appropriate time awaitHealthy()
and will work as usual. The only requirement for ServiceManager is that all serivce are in the NEW state when the ServiceManager is constructed.
Service of Guava Document translation