@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();
   }
 }