@Override public final ListenableFuture<State> stop() { lock.lock(); try { if (state == State.NEW) { state = State.TERMINATED; terminated(State.NEW); startup.set(State.TERMINATED); shutdown.set(State.TERMINATED); } else if (state == State.STARTING) { shutdownWhenStartupFinishes = true; startup.set(State.STOPPING); } else if (state == State.RUNNING) { state = State.STOPPING; stopping(State.RUNNING); doStop(); } } catch (Throwable shutdownFailure) { // put the exception in the future, the user can get it via Future.get() notifyFailed(shutdownFailure); } finally { lock.unlock(); } return shutdown; }
/** * Implementing classes should invoke this method once their service has stopped. It will cause * the service to transition from {@link State#STOPPING} to {@link State#TERMINATED}. * * @throws IllegalStateException if the service is neither {@link State#STOPPING} nor {@link * State#RUNNING}. */ protected final void notifyStopped() { lock.lock(); try { if (state != State.STOPPING && state != State.RUNNING) { IllegalStateException failure = new IllegalStateException("Cannot notifyStopped() when the service is " + state); notifyFailed(failure); throw failure; } terminated(state); shutdown.set(State.TERMINATED); } finally { lock.unlock(); } }