org.glassfish.jersey.internal.guava.ListenableFuture Maven / Gradle / Ivy
Show all versions of jersey-common Show documentation
/*
* 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 org.glassfish.jersey.internal.guava;
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.
*
*
See the Guava User Guide article on
* {@code ListenableFuture}.
*
*
Purpose
*
*
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.
*
*
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);}
*
*
How to get an instance
*
*
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:
*
* - 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.)
*
- 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}.)
*
*
*
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 extends Future {
/**
* 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.
*
*
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#directExecutor direct execution}) will be caught and
* logged.
*
*
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:
*
*
* - If this {@code Future} is done at the time {@code addListener} is
* called, {@code addListener} will execute the listener inline.
*
- 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.
*
*
*
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.
*
*
This is the most general listener interface. For common operations
* performed using listeners, see {@link
* Futures}. For a simplified but general
* listener interface, see {@link
* 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);
}