org.docx4j.com.google.common.util.concurrent.ListenableFuture Maven / Gradle / Ivy
/*
* 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.docx4j.com.google.common.util.concurrent;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
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}.
*
*
This class is GWT-compatible.
*
*
Purpose
*
* The main purpose of {@code ListenableFuture} is to help you chain together a graph of
* asynchronous operations. You can chain them together manually with calls to methods like {@link
* Futures#transform(ListenableFuture, org.docx4j.com.google.common.base.Function, Executor)
* Futures.transform}, but you will often find it easier to use a framework. Frameworks automate the
* process, often adding features like monitoring, debugging, and cancellation. Examples of
* frameworks include:
*
*
* - Dagger Producers
*
*
* The main purpose of {@link #addListener addListener} is to support this chaining. You will
* rarely use it directly, in part because it does not provide direct access to the {@code Future}
* result. (If you want such access, you 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
*
* We encourage you to return {@code ListenableFuture} from your methods so that your users can
* take advantage of the {@linkplain Futures utilities built atop the class}. The way that you will
* create {@code ListenableFuture} instances depends on how you currently create {@code Future}
* instances:
*
*
* - If you receive them from an {@code java.util.concurrent.ExecutorService}, convert that
* service to a {@link ListeningExecutorService}, usually by calling {@link
* MoreExecutors#listeningDecorator(java.util.concurrent.ExecutorService)
* MoreExecutors.listeningDecorator}.
*
- If you manually call {@link java.util.concurrent.FutureTask#set} or a similar method,
* create a {@link SettableFuture} instead. (If your needs are more complex, you may prefer
* {@link AbstractFuture}.)
*
*
* Test doubles: If you need a {@code ListenableFuture} for your test, try a {@link
* SettableFuture} or one of the methods in the {@link Futures#immediateFuture Futures.immediate*}
* family. Avoid creating a mock or stub {@code Future}. Mock and stub implementations are
* fragile because they assume that only certain methods will be called and because they often
* implement subtleties of the API improperly.
*
*
Custom implementation: Avoid implementing {@code ListenableFuture} from scratch. If you
* can't get by with the standard implementations, prefer to derive a new {@code Future} instance
* with the methods in {@link Futures} or, if necessary, to extend {@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}. Otherwise, avoid it. Heavyweight {@code directExecutor}
* listeners can cause problems, and these problems can be difficult to reproduce because they
* depend on timing. For example:
*
*
* - The listener may be executed by the caller of {@code addListener}. That caller may be a
* UI thread or other latency-sensitive thread. This can harm UI responsiveness.
*
- The listener may be executed by the thread that completes this {@code Future}. That
* thread may be an internal system thread such as an RPC network thread. Blocking that
* thread may stall progress of the whole system. It may even cause a deadlock.
*
- The listener may delay other listeners, even listeners that are not themselves {@code
* directExecutor} listeners.
*
*
* 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()}.
*
*
Memory consistency effects: Actions in a thread prior to adding a listener
* happen-before its execution begins, perhaps in another thread.
*
*
Guava implementations of {@code ListenableFuture} promptly release references to listeners
* after executing them.
*
* @param listener the listener to run when the computation is complete
* @param executor the executor to run the listener in
* @throws RejectedExecutionException if we tried to execute the listener immediately but the
* executor rejected it.
*/
void addListener(Runnable listener, Executor executor);
}