/* * 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. * *
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:
{@code * final String name = ...; * inFlight.add(name); * ListenableFuture* *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);}
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. * *
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#sameThreadExecutor inline execution}) will be caught and * logged. * *
Note: For fast, lightweight listeners that would be safe to execute in * any thread, consider {@link MoreExecutors#sameThreadExecutor}. For heavier * listeners, {@code sameThreadExecutor()} carries some caveats: First, the * thread that the listener runs in depends on whether the {@code Future} is * done at the time it is added and on whether it is ever canclled. In * particular, listeners may run in the thread that calls {@code addListener} * or the thread that calls {@code cancel}. Second, listeners may run in an * internal thread of the system responsible for the input {@code Future}, * such as an RPC network thread. Finally, during the execution of a {@code * sameThreadExecutor()} listener, all other registered but unexecuted * listeners are prevented from running, even if those listeners are to run * in other executors. * *
This is the most general listener interface. * For common operations performed using listeners, * see {@link com.google.common.util.concurrent.Futures} * * @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); }