1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.util.concurrent; 18 19 import java.util.concurrent.Executor; 20 import java.util.concurrent.ExecutorService; 21 import java.util.concurrent.Future; 22 import java.util.concurrent.FutureTask; 23 import java.util.concurrent.RejectedExecutionException; 24 25 /** 26 * A {@link Future} that accepts completion listeners. Each listener has an 27 * associated executor, and it is invoked using this executor once the future's 28 * computation is {@linkplain Future#isDone() complete}. If the computation has 29 * already completed when the listener is added, the listener will execute 30 * immediately. 31 * 32 * <p>See the Guava User Guide article on <a href= 33 * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained"> 34 * {@code ListenableFuture}</a>. 35 * 36 * <h3>Purpose</h3> 37 * 38 * <p>Most commonly, {@code ListenableFuture} is used as an input to another 39 * derived {@code Future}, as in {@link Futures#allAsList(Iterable) 40 * Futures.allAsList}. Many such methods are impossible to implement efficiently 41 * without listener support. 42 * 43 * <p>It is possible to call {@link #addListener addListener} directly, but this 44 * is uncommon because the {@code Runnable} interface does not provide direct 45 * access to the {@code Future} result. (Users who want such access may prefer 46 * {@link Futures#addCallback Futures.addCallback}.) Still, direct {@code 47 * addListener} calls are occasionally useful:<pre> {@code 48 * final String name = ...; 49 * inFlight.add(name); 50 * ListenableFuture<Result> future = service.query(name); 51 * future.addListener(new Runnable() { 52 * public void run() { 53 * processedCount.incrementAndGet(); 54 * inFlight.remove(name); 55 * lastProcessed.set(name); 56 * logger.info("Done with {0}", name); 57 * } 58 * }, executor);}</pre> 59 * 60 * <h3>How to get an instance</h3> 61 * 62 * <p>Developers are encouraged to return {@code ListenableFuture} from their 63 * methods so that users can take advantages of the utilities built atop the 64 * class. The way that they will create {@code ListenableFuture} instances 65 * depends on how they currently create {@code Future} instances: 66 * <ul> 67 * <li>If they are returned from an {@code ExecutorService}, convert that 68 * service to a {@link ListeningExecutorService}, usually by calling {@link 69 * MoreExecutors#listeningDecorator(ExecutorService) 70 * MoreExecutors.listeningDecorator}. (Custom executors may find it more 71 * convenient to use {@link ListenableFutureTask} directly.) 72 * <li>If they are manually filled in by a call to {@link FutureTask#set} or a 73 * similar method, create a {@link SettableFuture} instead. (Users with more 74 * complex needs may prefer {@link AbstractFuture}.) 75 * </ul> 76 * 77 * <p>Occasionally, an API will return a plain {@code Future} and it will be 78 * impossible to change the return type. For this case, we provide a more 79 * expensive workaround in {@code JdkFutureAdapters}. However, when possible, it 80 * is more efficient and reliable to create a {@code ListenableFuture} directly. 81 * 82 * @author Sven Mawson 83 * @author Nishant Thakkar 84 * @since 1.0 85 */ 86 public interface ListenableFuture<V> extends Future<V> { 87 /** 88 * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on 89 * the given executor. The listener will run when the {@code Future}'s 90 * computation is {@linkplain Future#isDone() complete} or, if the computation 91 * is already complete, immediately. 92 * 93 * <p>There is no guaranteed ordering of execution of listeners, but any 94 * listener added through this method is guaranteed to be called once the 95 * computation is complete. 96 * 97 * <p>Exceptions thrown by a listener will be propagated up to the executor. 98 * Any exception thrown during {@code Executor.execute} (e.g., a {@code 99 * RejectedExecutionException} or an exception thrown by {@linkplain 100 * MoreExecutors#directExecutor direct execution}) will be caught and 101 * logged. 102 * 103 * <p>Note: For fast, lightweight listeners that would be safe to execute in 104 * any thread, consider {@link MoreExecutors#directExecutor}. For heavier 105 * listeners, {@code directExecutor()} carries some caveats. For 106 * example, the listener may run on an unpredictable or undesirable thread: 107 * 108 * <ul> 109 * <li>If this {@code Future} is done at the time {@code addListener} is 110 * called, {@code addListener} will execute the listener inline. 111 * <li>If this {@code Future} is not yet done, {@code addListener} will 112 * schedule the listener to be run by the thread that completes this {@code 113 * Future}, which may be an internal system thread such as an RPC network 114 * thread. 115 * </ul> 116 * 117 * <p>Also note that, regardless of which thread executes the 118 * {@code directExecutor()} listener, all other registered but unexecuted 119 * listeners are prevented from running during its execution, even if those 120 * listeners are to run in other executors. 121 * 122 * <p>This is the most general listener interface. For common operations 123 * performed using listeners, see {@link 124 * com.google.common.util.concurrent.Futures}. For a simplified but general 125 * listener interface, see {@link 126 * com.google.common.util.concurrent.Futures#addCallback addCallback()}. 127 * 128 * @param listener the listener to run when the computation is complete 129 * @param executor the executor to run the listener in 130 * @throws NullPointerException if the executor or listener was null 131 * @throws RejectedExecutionException if we tried to execute the listener 132 * immediately but the executor rejected it. 133 */ addListener(Runnable listener, Executor executor)134 void addListener(Runnable listener, Executor executor); 135 } 136