synchronized block." Each
enqueued callable will not be submitted to its associated executor until the
previous callable has returned -- and, if the previous callable was an AsyncCallable, not
until the Future it returned is done (successful, failed, or
cancelled).
This class serializes execution of submitted tasks but not any listeners of those tasks.
Submitted tasks have a happens-before order as defined in the Java Language Specification.
Tasks execute with the same happens-before order that the function calls to submit and
submitAsync that submitted those tasks had.
This class has limited support for cancellation and other "early completions":
submit and submitAsync return a Future that can be
cancelled, cancellation never propagates to a task that has started to run -- neither to
the callable itself nor to any Future returned by an AsyncCallable.
(However, cancellation can prevent an unstarted task from running.) Therefore, the
next task will wait for any running callable (or pending Future returned by an
AsyncCallable) to complete, without interrupting it (and without calling cancel on the Future). So beware: Even if you cancel every preceding Future returned by this class, the next task may still have to wait..
AsyncCallable returns a Future, this class considers that task to
be "done" as soon as that Future completes in any way. Notably, a Future is "completed" even if it is cancelled while its underlying work continues on a
thread, an RPC, etc. The Future is also "completed" if it fails "early" -- for
example, if the deadline expires on a Future returned from Futures#withTimeout while the Future it wraps continues its underlying work. So
beware: Your AsyncCallable should not complete its Future until it is
safe for the next task to start.
This class is similar to MoreExecutors#newSequentialExecutor. This class is different
in a few ways:
AsyncCallable.
newSequentialExecutor does
not return Future objects, so it doesn't support interruption directly, either.
However, utilities that use that executor have the ability to interrupt tasks
running on it. This class, by contrast, does not expose an Executor API.)
If you don't need the features of this class, you may prefer newSequentialExecutor for
its simplicity and ability to accommodate interruption.
| Modifier and Type | Class and Description |
|---|---|
| pack-priv static enum | |
| private static class | ExecutionSequencer.
This class helps avoid a StackOverflowError when large numbers of tasks are submitted with
|
| private static class | ExecutionSequencer.
This object is unsafely published, but avoids problematic races by relying exclusively on the identity equality of its Thread field so that the task field is only accessed by a single thread. |
| Modifier and Type | Field and Description |
|---|---|
| private ExecutionSequencer. | |
| private final AtomicReference | ref
This reference acts as a pointer tracking the head of a linked list of ListenableFutures. |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public static ExecutionSequencer | |
| public <T extends @Nullable Object> ListenableFuture | |
| public <T extends @Nullable Object> ListenableFuture | submitAsync(AsyncCallable<T> callable, Executor executor)
Enqueues a task to run when the previous task (if any) completes. |
| latestTaskQueue | back to summary |
|---|---|
| private ExecutionSequencer. | |
| ref | back to summary |
|---|---|
| private final AtomicReference<ListenableFuture<@Nullable Void>> ref This reference acts as a pointer tracking the head of a linked list of ListenableFutures. | |
| ExecutionSequencer | back to summary |
|---|---|
| private ExecutionSequencer() | |
| create | back to summary |
|---|---|
| public static ExecutionSequencer create() Creates a new instance. | |
| submit | back to summary |
|---|---|
| public <T extends @Nullable Object> ListenableFuture Enqueues a task to run when the previous task (if any) completes. Cancellation does not propagate from the output future to a callable that has begun to
execute, but if the output future is cancelled before | |
| submitAsync | back to summary |
|---|---|
| public <T extends @Nullable Object> ListenableFuture Enqueues a task to run when the previous task (if any) completes. Cancellation does not propagate from the output future to the future returned from | |
| Modifier and Type | Field and Description |
|---|---|
| public static final ExecutionSequencer. | |
| public static final ExecutionSequencer. | |
| public static final ExecutionSequencer. |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public static ExecutionSequencer. | |
| public static ExecutionSequencer. |
| CANCELLED | back to summary |
|---|---|
| public static final ExecutionSequencer. | |
| NOT_RUN | back to summary |
|---|---|
| public static final ExecutionSequencer. | |
| STARTED | back to summary |
|---|---|
| public static final ExecutionSequencer. | |
| RunningState | back to summary |
|---|---|
| private RunningState() | |
| valueOf | back to summary |
|---|---|
| public static ExecutionSequencer. | |
| values | back to summary |
|---|---|
| public static ExecutionSequencer. | |
MoreExecutors#directExecutor. Normally, when the first future completes, all the other
tasks would be called recursively. Here, we detect that the delegate executor is executing
inline, and maintain a queue to dispatch tasks iteratively. There is one instance of this class
per call to submit() or submitAsync(), and each instance supports only one call to execute().
This class would certainly be simpler and easier to reason about if it were built with ThreadLocal; however, ThreadLocal is not well optimized for the case where the ThreadLocal is non-static, and is initialized/removed frequently - this causes churn in the Thread specific hashmaps. Using a static ThreadLocal to avoid that overhead would mean that different ExecutionSequencer objects interfere with each other, which would be undesirable, in addition to increasing the memory footprint of every thread that interacted with it. In order to release entries in thread-specific maps when the ThreadLocal object itself is no longer referenced, ThreadLocal is usually implemented with a WeakReference, which can have negative performance properties; for example, calling WeakReference.get() on Android will block during an otherwise-concurrent GC cycle.
| Modifier and Type | Field and Description |
|---|---|
| pack-priv Executor | delegate
Executor the task was set to run on. |
| pack-priv ExecutionSequencer | sequencer
Used to update and read the latestTaskQueue field. |
| pack-priv Thread | submitting
Thread that called execute(). |
| pack-priv Runnable | task
Set before calling delegate.execute(); set to null once run, so that it can be GCed; this object may live on after, if submitAsync returns an incomplete future. |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public void | execute(Runnable
the runnable task task)Implements java. |
| public void | |
| private boolean | |
| private boolean |
| delegate | back to summary |
|---|---|
| pack-priv Executor delegate Executor the task was set to run on. Set to null when the task has been queued, run, or cancelled. | |
| sequencer | back to summary |
|---|---|
| pack-priv ExecutionSequencer sequencer Used to update and read the latestTaskQueue field. Set to null once the runnable has been run or queued. | |
| submitting | back to summary |
|---|---|
| pack-priv Thread submitting Thread that called execute(). Set in execute, cleared when delegate.execute() returns. | |
| task | back to summary |
|---|---|
| pack-priv Runnable task Set before calling delegate.execute(); set to null once run, so that it can be GCed; this object may live on after, if submitAsync returns an incomplete future. | |
| TaskNonReentrantExecutor | back to summary |
|---|---|
| private TaskNonReentrantExecutor(Executor delegate, ExecutionSequencer sequencer) | |
| execute | back to summary |
|---|---|
| public void execute(Runnable task) Implements java. Doc from java. Executes the given command at some time in the future. The command
may execute in a new thread, in a pooled thread, or in the calling
thread, at the discretion of the | |
| run | back to summary |
|---|---|
| public void run() Implements java. Doc from java. Runs this operation.
| |
| trySetCancelled | back to summary |
|---|---|
| private boolean trySetCancelled() | |
| trySetStarted | back to summary |
|---|---|
| private boolean trySetStarted() | |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv Executor | nextExecutor
Only used by the thread associated with this object |
| pack-priv Runnable | nextTask
Only used by the thread associated with this object |
| pack-priv Thread | thread
This field is only used for identity comparisons with the current thread. |
| Access | Constructor and Description |
|---|---|
| private |
| nextExecutor | back to summary |
|---|---|
| pack-priv Executor nextExecutor Only used by the thread associated with this object | |
| nextTask | back to summary |
|---|---|
| pack-priv Runnable nextTask Only used by the thread associated with this object | |
| thread | back to summary |
|---|---|
| pack-priv Thread thread This field is only used for identity comparisons with the current thread. Field assignments are atomic, but do not provide happens-before ordering; however:
| |
| ThreadConfinedTaskQueue | back to summary |
|---|---|
| private ThreadConfinedTaskQueue() | |