| /* |
| * Copyright (C) 2009 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.util.concurrent; |
| |
| import com.google.common.annotations.Beta; |
| import com.google.common.base.Supplier; |
| import com.google.common.base.Throwables; |
| |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| |
| /** |
| * Base class for services that do not need a thread while "running" |
| * but may need one during startup and shutdown. Subclasses can |
| * implement {@link #startUp} and {@link #shutDown} methods, each |
| * which run in a executor which by default uses a separate thread |
| * for each method. |
| * |
| * @author Chris Nokleberg |
| * @since 1.0 |
| */ |
| @Beta |
| public abstract class AbstractIdleService implements Service { |
| |
| /* Thread names will look like {@code "MyService STARTING"}. */ |
| private final Supplier<String> threadNameSupplier = new Supplier<String>() { |
| @Override public String get() { |
| return serviceName() + " " + state(); |
| } |
| }; |
| |
| /* use AbstractService for state management */ |
| private final Service delegate = new AbstractService() { |
| @Override protected final void doStart() { |
| MoreExecutors.renamingDecorator(executor(), threadNameSupplier) |
| .execute(new Runnable() { |
| @Override public void run() { |
| try { |
| startUp(); |
| notifyStarted(); |
| } catch (Throwable t) { |
| notifyFailed(t); |
| throw Throwables.propagate(t); |
| } |
| } |
| }); |
| } |
| |
| @Override protected final void doStop() { |
| MoreExecutors.renamingDecorator(executor(), threadNameSupplier) |
| .execute(new Runnable() { |
| @Override public void run() { |
| try { |
| shutDown(); |
| notifyStopped(); |
| } catch (Throwable t) { |
| notifyFailed(t); |
| throw Throwables.propagate(t); |
| } |
| } |
| }); |
| } |
| }; |
| |
| /** Constructor for use by subclasses. */ |
| protected AbstractIdleService() {} |
| |
| /** Start the service. */ |
| protected abstract void startUp() throws Exception; |
| |
| /** Stop the service. */ |
| protected abstract void shutDown() throws Exception; |
| |
| /** |
| * Returns the {@link Executor} that will be used to run this service. |
| * Subclasses may override this method to use a custom {@link Executor}, which |
| * may configure its worker thread with a specific name, thread group or |
| * priority. The returned executor's {@link Executor#execute(Runnable) |
| * execute()} method is called when this service is started and stopped, |
| * and should return promptly. |
| */ |
| protected Executor executor() { |
| return new Executor() { |
| @Override public void execute(Runnable command) { |
| MoreExecutors.newThread(threadNameSupplier.get(), command).start(); |
| } |
| }; |
| } |
| |
| @Override public String toString() { |
| return serviceName() + " [" + state() + "]"; |
| } |
| |
| @Override public final boolean isRunning() { |
| return delegate.isRunning(); |
| } |
| |
| @Override public final State state() { |
| return delegate.state(); |
| } |
| |
| /** |
| * @since 13.0 |
| */ |
| @Override public final void addListener(Listener listener, Executor executor) { |
| delegate.addListener(listener, executor); |
| } |
| |
| /** |
| * @since 14.0 |
| */ |
| @Override public final Throwable failureCause() { |
| return delegate.failureCause(); |
| } |
| |
| /** |
| * @since 15.0 |
| */ |
| @Override public final Service startAsync() { |
| delegate.startAsync(); |
| return this; |
| } |
| |
| /** |
| * @since 15.0 |
| */ |
| @Override public final Service stopAsync() { |
| delegate.stopAsync(); |
| return this; |
| } |
| |
| /** |
| * @since 15.0 |
| */ |
| @Override public final void awaitRunning() { |
| delegate.awaitRunning(); |
| } |
| |
| /** |
| * @since 15.0 |
| */ |
| @Override public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { |
| delegate.awaitRunning(timeout, unit); |
| } |
| |
| /** |
| * @since 15.0 |
| */ |
| @Override public final void awaitTerminated() { |
| delegate.awaitTerminated(); |
| } |
| |
| /** |
| * @since 15.0 |
| */ |
| @Override public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { |
| delegate.awaitTerminated(timeout, unit); |
| } |
| |
| /** |
| * Returns the name of this service. {@link AbstractIdleService} may include the name in debugging |
| * output. |
| * |
| * @since 14.0 |
| */ |
| protected String serviceName() { |
| return getClass().getSimpleName(); |
| } |
| } |