/* * Copyright (C) 2007 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 java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.RejectedExecutionException; /** * A {@link Future} that accepts completion listeners. Each listener has an * associated executor, and it is invoked using this executor once the future's * computation is {@linkplain Future#isDone() complete}. If the computation has * already completed when the listener is added, the listener will execute * immediately. * * <p>See the Guava User Guide article on <a href= * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained"> * {@code ListenableFuture}</a>. * * <h3>Purpose</h3> * * <p>Most commonly, {@code ListenableFuture} is used as an input to another * derived {@code Future}, as in {@link Futures#allAsList(Iterable) * Futures.allAsList}. Many such methods are impossible to implement efficiently * without listener support. * * <p>It is possible to call {@link #addListener addListener} directly, but this * is uncommon because the {@code Runnable} interface does not provide direct * access to the {@code Future} result. (Users who want such access may prefer * {@link Futures#addCallback Futures.addCallback}.) Still, direct {@code * addListener} calls are occasionally useful:<pre> {@code * final String name = ...; * inFlight.add(name); * ListenableFuture<Result> future = service.query(name); * future.addListener(new Runnable() { * public void run() { * processedCount.incrementAndGet(); * inFlight.remove(name); * lastProcessed.set(name); * logger.info("Done with {0}", name); * } * }, executor);}</pre> * * <h3>How to get an instance</h3> * * <p>Developers are encouraged to return {@code ListenableFuture} from their * methods so that users can take advantages of the utilities built atop the * class. The way that they will create {@code ListenableFuture} instances * depends on how they currently create {@code Future} instances: * <ul> * <li>If they are returned from an {@code ExecutorService}, convert that * service to a {@link ListeningExecutorService}, usually by calling {@link * MoreExecutors#listeningDecorator(ExecutorService) * MoreExecutors.listeningDecorator}. (Custom executors may find it more * convenient to use {@link ListenableFutureTask} directly.) * <li>If they are manually filled in by a call to {@link FutureTask#set} or a * similar method, create a {@link SettableFuture} instead. (Users with more * complex needs may prefer {@link AbstractFuture}.) * </ul> * * <p>Occasionally, an API will return a plain {@code Future} and it will be * impossible to change the return type. For this case, we provide a more * expensive workaround in {@code JdkFutureAdapters}. However, when possible, it * is more efficient and reliable to create a {@code ListenableFuture} directly. * * @author Sven Mawson * @author Nishant Thakkar * @since 1.0 */ public interface ListenableFuture<V> extends Future<V> { /** * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on * the given executor. The listener will run when the {@code Future}'s * computation is {@linkplain Future#isDone() complete} or, if the computation * is already complete, immediately. * * <p>There is no guaranteed ordering of execution of listeners, but any * listener added through this method is guaranteed to be called once the * computation is complete. * * <p>Exceptions thrown by a listener will be propagated up to the executor. * Any exception thrown during {@code Executor.execute} (e.g., a {@code * RejectedExecutionException} or an exception thrown by {@linkplain * MoreExecutors#directExecutor direct execution}) will be caught and * logged. * * <p>Note: For fast, lightweight listeners that would be safe to execute in * any thread, consider {@link MoreExecutors#directExecutor}. For heavier * listeners, {@code directExecutor()} carries some caveats. For * example, the listener may run on an unpredictable or undesirable thread: * * <ul> * <li>If this {@code Future} is done at the time {@code addListener} is * called, {@code addListener} will execute the listener inline. * <li>If this {@code Future} is not yet done, {@code addListener} will * schedule the listener to be run by the thread that completes this {@code * Future}, which may be an internal system thread such as an RPC network * thread. * </ul> * * <p>Also note that, regardless of which thread executes the * {@code directExecutor()} listener, all other registered but unexecuted * listeners are prevented from running during its execution, even if those * listeners are to run in other executors. * * <p>This is the most general listener interface. For common operations * performed using listeners, see {@link * com.google.common.util.concurrent.Futures}. For a simplified but general * listener interface, see {@link * com.google.common.util.concurrent.Futures#addCallback addCallback()}. * * @param listener the listener to run when the computation is complete * @param executor the executor to run the listener in * @throws NullPointerException if the executor or listener was null * @throws RejectedExecutionException if we tried to execute the listener * immediately but the executor rejected it. */ void addListener(Runnable listener, Executor executor); }