public final class MoreExecutors
extends java.lang.Object
Executor
, ExecutorService
,
and ThreadFactory
.Modifier and Type | Class and Description |
---|---|
(package private) static class |
MoreExecutors.Application
Represents the current application to register shutdown hooks.
|
private static class |
MoreExecutors.DirectExecutorService |
private static class |
MoreExecutors.ListeningDecorator |
private static class |
MoreExecutors.ScheduledListeningDecorator |
Modifier | Constructor and Description |
---|---|
private |
MoreExecutors() |
Modifier and Type | Method and Description |
---|---|
static void |
addDelayedShutdownHook(java.util.concurrent.ExecutorService service,
java.time.Duration terminationTimeout)
Add a shutdown hook to wait for thread completion in the given
service . |
static void |
addDelayedShutdownHook(java.util.concurrent.ExecutorService service,
long terminationTimeout,
java.util.concurrent.TimeUnit timeUnit)
Add a shutdown hook to wait for thread completion in the given
service . |
static java.util.concurrent.Executor |
directExecutor()
Returns an
Executor that runs each task in the thread that invokes execute , as in ThreadPoolExecutor.CallerRunsPolicy . |
static java.util.concurrent.ExecutorService |
getExitingExecutorService(java.util.concurrent.ThreadPoolExecutor executor)
Converts the given ThreadPoolExecutor into an ExecutorService that exits when the application
is complete.
|
static java.util.concurrent.ExecutorService |
getExitingExecutorService(java.util.concurrent.ThreadPoolExecutor executor,
java.time.Duration terminationTimeout)
Converts the given ThreadPoolExecutor into an ExecutorService that exits when the application
is complete.
|
static java.util.concurrent.ExecutorService |
getExitingExecutorService(java.util.concurrent.ThreadPoolExecutor executor,
long terminationTimeout,
java.util.concurrent.TimeUnit timeUnit)
Converts the given ThreadPoolExecutor into an ExecutorService that exits when the application
is complete.
|
static java.util.concurrent.ScheduledExecutorService |
getExitingScheduledExecutorService(java.util.concurrent.ScheduledThreadPoolExecutor executor)
Converts the given ScheduledThreadPoolExecutor into a ScheduledExecutorService that exits when
the application is complete.
|
static java.util.concurrent.ScheduledExecutorService |
getExitingScheduledExecutorService(java.util.concurrent.ScheduledThreadPoolExecutor executor,
java.time.Duration terminationTimeout)
Converts the given ScheduledThreadPoolExecutor into a ScheduledExecutorService that exits when
the application is complete.
|
static java.util.concurrent.ScheduledExecutorService |
getExitingScheduledExecutorService(java.util.concurrent.ScheduledThreadPoolExecutor executor,
long terminationTimeout,
java.util.concurrent.TimeUnit timeUnit)
Converts the given ScheduledThreadPoolExecutor into a ScheduledExecutorService that exits when
the application is complete.
|
(package private) static <T> T |
invokeAnyImpl(ListeningExecutorService executorService,
java.util.Collection<? extends java.util.concurrent.Callable<T>> tasks,
boolean timed,
java.time.Duration timeout)
An implementation of
ExecutorService.invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) for ListeningExecutorService
implementations. |
(package private) static <T> T |
invokeAnyImpl(ListeningExecutorService executorService,
java.util.Collection<? extends java.util.concurrent.Callable<T>> tasks,
boolean timed,
long timeout,
java.util.concurrent.TimeUnit unit)
An implementation of
ExecutorService.invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) for ListeningExecutorService
implementations. |
private static boolean |
isAppEngineWithApiClasses() |
static ListeningExecutorService |
listeningDecorator(java.util.concurrent.ExecutorService delegate)
Creates an
ExecutorService whose submit and invokeAll methods submit
ListenableFutureTask instances to the given delegate executor. |
static ListeningScheduledExecutorService |
listeningDecorator(java.util.concurrent.ScheduledExecutorService delegate)
Creates a
ScheduledExecutorService whose submit and invokeAll methods
submit ListenableFutureTask instances to the given delegate executor. |
static ListeningExecutorService |
newDirectExecutorService()
Creates an executor service that runs each task in the thread that invokes
execute/submit , as in ThreadPoolExecutor.CallerRunsPolicy . |
static java.util.concurrent.Executor |
newSequentialExecutor(java.util.concurrent.Executor delegate)
Returns an
Executor that runs each task executed sequentially, such that no two tasks
are running concurrently. |
(package private) static java.lang.Thread |
newThread(java.lang.String name,
java.lang.Runnable runnable)
Creates a thread using
platformThreadFactory() , and sets its name to name unless
changing the name is forbidden by the security manager. |
static java.util.concurrent.ThreadFactory |
platformThreadFactory()
Returns a default thread factory used to create new threads.
|
(package private) static java.util.concurrent.Executor |
rejectionPropagatingExecutor(java.util.concurrent.Executor delegate,
AbstractFuture<?> future)
Returns an Executor that will propagate
RejectedExecutionException from the delegate
executor to the given future . |
(package private) static java.util.concurrent.ExecutorService |
renamingDecorator(java.util.concurrent.ExecutorService service,
Supplier<java.lang.String> nameSupplier)
Creates an
ExecutorService that renames the threads that its tasks run
in. |
(package private) static java.util.concurrent.Executor |
renamingDecorator(java.util.concurrent.Executor executor,
Supplier<java.lang.String> nameSupplier)
Creates an
Executor that renames the threads that its tasks run in. |
(package private) static java.util.concurrent.ScheduledExecutorService |
renamingDecorator(java.util.concurrent.ScheduledExecutorService service,
Supplier<java.lang.String> nameSupplier)
Creates a
ScheduledExecutorService that renames the threads that its
tasks run in. |
static boolean |
shutdownAndAwaitTermination(java.util.concurrent.ExecutorService service,
java.time.Duration timeout)
Shuts down the given executor service gradually, first disabling new submissions and later, if
necessary, cancelling remaining tasks.
|
static boolean |
shutdownAndAwaitTermination(java.util.concurrent.ExecutorService service,
long timeout,
java.util.concurrent.TimeUnit unit)
Shuts down the given executor service gradually, first disabling new submissions and later, if
necessary, cancelling remaining tasks.
|
private static <T> ListenableFuture<T> |
submitAndAddQueueListener(ListeningExecutorService executorService,
java.util.concurrent.Callable<T> task,
java.util.concurrent.BlockingQueue<java.util.concurrent.Future<T>> queue)
Submits the task and adds a listener that adds the future to
queue when it completes. |
private static void |
useDaemonThreadFactory(java.util.concurrent.ThreadPoolExecutor executor) |
public static java.util.concurrent.ExecutorService getExitingExecutorService(java.util.concurrent.ThreadPoolExecutor executor, java.time.Duration terminationTimeout)
This is mainly for fixed thread pools. See Executors.newFixedThreadPool(int)
.
executor
- the executor to modify to make sure it exits when the application is finishedterminationTimeout
- how long to wait for the executor to finish before terminating the
JVMpublic static java.util.concurrent.ExecutorService getExitingExecutorService(java.util.concurrent.ThreadPoolExecutor executor, long terminationTimeout, java.util.concurrent.TimeUnit timeUnit)
This is mainly for fixed thread pools. See Executors.newFixedThreadPool(int)
.
executor
- the executor to modify to make sure it exits when the application is finishedterminationTimeout
- how long to wait for the executor to finish before terminating the
JVMtimeUnit
- unit of time for the time parameterpublic static java.util.concurrent.ExecutorService getExitingExecutorService(java.util.concurrent.ThreadPoolExecutor executor)
This method waits 120 seconds before continuing with JVM termination, even if the executor has not finished its work.
This is mainly for fixed thread pools. See Executors.newFixedThreadPool(int)
.
executor
- the executor to modify to make sure it exits when the application is finishedpublic static java.util.concurrent.ScheduledExecutorService getExitingScheduledExecutorService(java.util.concurrent.ScheduledThreadPoolExecutor executor, java.time.Duration terminationTimeout)
This is mainly for fixed thread pools. See Executors.newScheduledThreadPool(int)
.
executor
- the executor to modify to make sure it exits when the application is finishedterminationTimeout
- how long to wait for the executor to finish before terminating the
JVMpublic static java.util.concurrent.ScheduledExecutorService getExitingScheduledExecutorService(java.util.concurrent.ScheduledThreadPoolExecutor executor, long terminationTimeout, java.util.concurrent.TimeUnit timeUnit)
This is mainly for fixed thread pools. See Executors.newScheduledThreadPool(int)
.
executor
- the executor to modify to make sure it exits when the application is finishedterminationTimeout
- how long to wait for the executor to finish before terminating the
JVMtimeUnit
- unit of time for the time parameterpublic static java.util.concurrent.ScheduledExecutorService getExitingScheduledExecutorService(java.util.concurrent.ScheduledThreadPoolExecutor executor)
This method waits 120 seconds before continuing with JVM termination, even if the executor has not finished its work.
This is mainly for fixed thread pools. See Executors.newScheduledThreadPool(int)
.
executor
- the executor to modify to make sure it exits when the application is finishedpublic static void addDelayedShutdownHook(java.util.concurrent.ExecutorService service, java.time.Duration terminationTimeout)
service
.
This is useful if the given service uses daemon threads, and we want to keep the JVM from
exiting immediately on shutdown, instead giving these daemon threads a chance to terminate
normally.service
- ExecutorService which uses daemon threadsterminationTimeout
- how long to wait for the executor to finish before terminating the
JVMpublic static void addDelayedShutdownHook(java.util.concurrent.ExecutorService service, long terminationTimeout, java.util.concurrent.TimeUnit timeUnit)
service
.
This is useful if the given service uses daemon threads, and we want to keep the JVM from
exiting immediately on shutdown, instead giving these daemon threads a chance to terminate
normally.service
- ExecutorService which uses daemon threadsterminationTimeout
- how long to wait for the executor to finish before terminating the
JVMtimeUnit
- unit of time for the time parameterprivate static void useDaemonThreadFactory(java.util.concurrent.ThreadPoolExecutor executor)
public static ListeningExecutorService newDirectExecutorService()
execute/submit
, as in ThreadPoolExecutor.CallerRunsPolicy
. This applies both to
individually submitted tasks and to collections of tasks submitted via invokeAll
or
invokeAny
. In the latter case, tasks will run serially on the calling thread. Tasks are
run to completion before a Future
is returned to the caller (unless the executor has
been shutdown).
Although all tasks are immediately executed in the thread that submitted the task, this
ExecutorService
imposes a small locking overhead on each task submission in order to
implement shutdown and termination behavior.
The implementation deviates from the ExecutorService
specification with regards to
the shutdownNow
method. First, "best-effort" with regards to canceling running tasks is
implemented as "no-effort". No interrupts or other attempts are made to stop threads executing
tasks. Second, the returned list will always be empty, as any submitted task is considered to
have started execution. This applies also to tasks given to invokeAll
or invokeAny
which are pending serial execution, even the subset of the tasks that have not yet
started execution. It is unclear from the ExecutorService
specification if these should
be included, and it's much easier to implement the interpretation that they not be. Finally, a
call to shutdown
or shutdownNow
may result in concurrent calls to invokeAll/invokeAny
throwing RejectedExecutionException, although a subset of the tasks may
already have been executed.
public static java.util.concurrent.Executor directExecutor()
Executor
that runs each task in the thread that invokes execute
, as in ThreadPoolExecutor.CallerRunsPolicy
.
This executor is appropriate for tasks that are lightweight and not deeply chained.
Inappropriate directExecutor
usage can cause problems, and these problems can be
difficult to reproduce because they depend on timing. For example:
ListenableFuture
listener is registered to run under directExecutor
, the listener can execute in any of three possible threads:
ListenableFuture
that's already
complete, the listener runs immediately in that thread.
ListenableFuture
that's
incomplete and the ListenableFuture
later completes normally, the
listener runs in the the thread that completes the ListenableFuture
.
ListenableFuture
and the ListenableFuture
gets cancelled, the listener runs immediately in the the thread
that cancelled the Future
.
directExecutor
tasks.
future.transform(...).transform(...).transform(...)....
), they may overflow the stack.
(In simple cases, callers can avoid this by registering all tasks with the same newSequentialExecutor(java.util.concurrent.Executor)
wrapper around directExecutor()
. More
complex cases may require using thread pools or making deeper changes.)
Runnable
, it is not necessarily seen by any
UncaughtExceptionHandler
for the thread. For example, if the callback passed to
Futures.addCallback(com.google.common.util.concurrent.ListenableFuture<V>, com.google.common.util.concurrent.FutureCallback<? super V>, java.util.concurrent.Executor)
throws an exception, that exception will be typically be
logged by the ListenableFuture
implementation, even if the thread is configured
to do something different. In other cases, no code will catch the exception, and it may
terminate whichever thread happens to trigger the execution.
ListenableFuture
listeners, should take care not to do so while holding a lock. Additionally,
as a further line of defense, prefer not to perform any locking inside a task that will be run
under directExecutor
: Not only might the wait for a lock be long, but if the running
thread was holding a lock, the listener may deadlock or break lock isolation.
This instance is equivalent to:
final class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
This should be preferred to newDirectExecutorService()
because implementing the
ExecutorService
subinterface necessitates significant performance overhead.
public static java.util.concurrent.Executor newSequentialExecutor(java.util.concurrent.Executor delegate)
Executor
that runs each task executed sequentially, such that no two tasks
are running concurrently.
executed 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 `execute()`
that submitted those tasks had.
The executor uses delegate
in order to execute
each task in
turn, and does not create any threads of its own.
After execution begins on a thread from the delegate
Executor
, tasks are
polled and executed from a task queue until there are no more tasks. The thread will not be
released until there are no more tasks to run.
If a task is submitted while a thread is executing tasks from the task queue, the thread will not be released until that submitted task is also complete.
If a task is interrupted while a task is running:
delegate
Executor may process the interrupt.
RuntimeException
s thrown by tasks are simply logged and the executor keeps trucking.
If an Error
is thrown, the error will propagate and execution will stop until the next
time a task is submitted.
When an Error
is thrown by an executed task, previously submitted tasks may never
run. An attempt will be made to restart execution on the next call to execute
. If the
delegate
has begun to reject execution, the previously submitted tasks may never run,
despite not throwing a RejectedExecutionException synchronously with the call to execute
. If this behaviour is problematic, use an Executor with a single thread (e.g. Executors.newSingleThreadExecutor()
).
sequentialExecutor
)public static ListeningExecutorService listeningDecorator(java.util.concurrent.ExecutorService delegate)
ExecutorService
whose submit
and invokeAll
methods submit
ListenableFutureTask
instances to the given delegate executor. Those methods, as well
as execute
and invokeAny
, are implemented in terms of calls to delegate.execute
. All other methods are forwarded unchanged to the delegate. This implies that
the returned ListeningExecutorService
never calls the delegate's submit
, invokeAll
, and invokeAny
methods, so any special handling of tasks must be implemented
in the delegate's execute
method or by wrapping the returned ListeningExecutorService
.
If the delegate executor was already an instance of ListeningExecutorService
, it is
returned untouched, and the rest of this documentation does not apply.
public static ListeningScheduledExecutorService listeningDecorator(java.util.concurrent.ScheduledExecutorService delegate)
ScheduledExecutorService
whose submit
and invokeAll
methods
submit ListenableFutureTask
instances to the given delegate executor. Those methods, as
well as execute
and invokeAny
, are implemented in terms of calls to delegate.execute
. All other methods are forwarded unchanged to the delegate. This implies that
the returned ListeningScheduledExecutorService
never calls the delegate's submit
, invokeAll
, and invokeAny
methods, so any special handling of tasks
must be implemented in the delegate's execute
method or by wrapping the returned ListeningScheduledExecutorService
.
If the delegate executor was already an instance of ListeningScheduledExecutorService
, it is returned untouched, and the rest of this
documentation does not apply.
static <T> T invokeAnyImpl(ListeningExecutorService executorService, java.util.Collection<? extends java.util.concurrent.Callable<T>> tasks, boolean timed, java.time.Duration timeout) throws java.lang.InterruptedException, java.util.concurrent.ExecutionException, java.util.concurrent.TimeoutException
ExecutorService.invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>)
for ListeningExecutorService
implementations.java.lang.InterruptedException
java.util.concurrent.ExecutionException
java.util.concurrent.TimeoutException
static <T> T invokeAnyImpl(ListeningExecutorService executorService, java.util.Collection<? extends java.util.concurrent.Callable<T>> tasks, boolean timed, long timeout, java.util.concurrent.TimeUnit unit) throws java.lang.InterruptedException, java.util.concurrent.ExecutionException, java.util.concurrent.TimeoutException
ExecutorService.invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>)
for ListeningExecutorService
implementations.java.lang.InterruptedException
java.util.concurrent.ExecutionException
java.util.concurrent.TimeoutException
private static <T> ListenableFuture<T> submitAndAddQueueListener(ListeningExecutorService executorService, java.util.concurrent.Callable<T> task, java.util.concurrent.BlockingQueue<java.util.concurrent.Future<T>> queue)
queue
when it completes.public static java.util.concurrent.ThreadFactory platformThreadFactory()
When running on AppEngine with access to AppEngine legacy
APIs, this method returns ThreadManager.currentRequestThreadFactory()
. Otherwise,
it returns Executors.defaultThreadFactory()
.
private static boolean isAppEngineWithApiClasses()
static java.lang.Thread newThread(java.lang.String name, java.lang.Runnable runnable)
platformThreadFactory()
, and sets its name to name
unless
changing the name is forbidden by the security manager.static java.util.concurrent.Executor renamingDecorator(java.util.concurrent.Executor executor, Supplier<java.lang.String> nameSupplier)
Executor
that renames the threads
that its tasks run in.
The names are retrieved from the nameSupplier
on the thread that is being renamed
right before each task is run. The renaming is best effort, if a SecurityManager
prevents the renaming then it will be skipped but the tasks will still execute.
executor
- The executor to decoratenameSupplier
- The source of names for each taskstatic java.util.concurrent.ExecutorService renamingDecorator(java.util.concurrent.ExecutorService service, Supplier<java.lang.String> nameSupplier)
ExecutorService
that renames the threads
that its tasks run
in.
The names are retrieved from the nameSupplier
on the thread that is being renamed
right before each task is run. The renaming is best effort, if a SecurityManager
prevents the renaming then it will be skipped but the tasks will still execute.
service
- The executor to decoratenameSupplier
- The source of names for each taskstatic java.util.concurrent.ScheduledExecutorService renamingDecorator(java.util.concurrent.ScheduledExecutorService service, Supplier<java.lang.String> nameSupplier)
ScheduledExecutorService
that renames the threads
that its
tasks run in.
The names are retrieved from the nameSupplier
on the thread that is being renamed
right before each task is run. The renaming is best effort, if a SecurityManager
prevents the renaming then it will be skipped but the tasks will still execute.
service
- The executor to decoratenameSupplier
- The source of names for each taskpublic static boolean shutdownAndAwaitTermination(java.util.concurrent.ExecutorService service, java.time.Duration timeout)
The method takes the following steps:
ExecutorService.shutdown()
, disabling acceptance of new submitted tasks.
ExecutorService.shutdownNow()
, cancelling
pending tasks and interrupting running tasks.
If, at any step of the process, the calling thread is interrupted, the method calls ExecutorService.shutdownNow()
and returns.
service
- the ExecutorService
to shut downtimeout
- the maximum time to wait for the ExecutorService
to terminatetrue
if the ExecutorService
was terminated successfully, false
if the call timed out or was interruptedpublic static boolean shutdownAndAwaitTermination(java.util.concurrent.ExecutorService service, long timeout, java.util.concurrent.TimeUnit unit)
The method takes the following steps:
ExecutorService.shutdown()
, disabling acceptance of new submitted tasks.
ExecutorService.shutdownNow()
, cancelling
pending tasks and interrupting running tasks.
If, at any step of the process, the calling thread is interrupted, the method calls ExecutorService.shutdownNow()
and returns.
service
- the ExecutorService
to shut downtimeout
- the maximum time to wait for the ExecutorService
to terminateunit
- the time unit of the timeout argumenttrue
if the ExecutorService
was terminated successfully, false
if the call timed out or was interruptedstatic java.util.concurrent.Executor rejectionPropagatingExecutor(java.util.concurrent.Executor delegate, AbstractFuture<?> future)
RejectedExecutionException
from the delegate
executor to the given future
.
Note, the returned executor can only be used once.