Class MoreExecutors

    • Method Detail

      • getExitingExecutorService

        @Beta
        @GwtIncompatible
        public static ExecutorService getExitingExecutorService​(ThreadPoolExecutor executor,
                                                                Duration terminationTimeout)
        Converts the given ThreadPoolExecutor into an ExecutorService that exits when the application is complete. It does so by using daemon threads and adding a shutdown hook to wait for their completion.

        This is mainly for fixed thread pools. See Executors.newFixedThreadPool(int).

        Parameters:
        executor - the executor to modify to make sure it exits when the application is finished
        terminationTimeout - how long to wait for the executor to finish before terminating the JVM
        Returns:
        an unmodifiable version of the input which will not hang the JVM
        Since:
        28.0
      • getExitingExecutorService

        @Beta
        @GwtIncompatible
        public static ExecutorService getExitingExecutorService​(ThreadPoolExecutor executor,
                                                                long terminationTimeout,
                                                                TimeUnit timeUnit)
        Converts the given ThreadPoolExecutor into an ExecutorService that exits when the application is complete. It does so by using daemon threads and adding a shutdown hook to wait for their completion.

        This is mainly for fixed thread pools. See Executors.newFixedThreadPool(int).

        Parameters:
        executor - the executor to modify to make sure it exits when the application is finished
        terminationTimeout - how long to wait for the executor to finish before terminating the JVM
        timeUnit - unit of time for the time parameter
        Returns:
        an unmodifiable version of the input which will not hang the JVM
      • getExitingExecutorService

        @Beta
        @GwtIncompatible
        public static ExecutorService getExitingExecutorService​(ThreadPoolExecutor executor)
        Converts the given ThreadPoolExecutor into an ExecutorService that exits when the application is complete. It does so by using daemon threads and adding a shutdown hook to wait for their completion.

        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).

        Parameters:
        executor - the executor to modify to make sure it exits when the application is finished
        Returns:
        an unmodifiable version of the input which will not hang the JVM
      • getExitingScheduledExecutorService

        @Beta
        @GwtIncompatible
        public static ScheduledExecutorService getExitingScheduledExecutorService​(ScheduledThreadPoolExecutor executor,
                                                                                  Duration terminationTimeout)
        Converts the given ScheduledThreadPoolExecutor into a ScheduledExecutorService that exits when the application is complete. It does so by using daemon threads and adding a shutdown hook to wait for their completion.

        This is mainly for fixed thread pools. See Executors.newScheduledThreadPool(int).

        Parameters:
        executor - the executor to modify to make sure it exits when the application is finished
        terminationTimeout - how long to wait for the executor to finish before terminating the JVM
        Returns:
        an unmodifiable version of the input which will not hang the JVM
        Since:
        28.0
      • getExitingScheduledExecutorService

        @Beta
        @GwtIncompatible
        public static ScheduledExecutorService getExitingScheduledExecutorService​(ScheduledThreadPoolExecutor executor,
                                                                                  long terminationTimeout,
                                                                                  TimeUnit timeUnit)
        Converts the given ScheduledThreadPoolExecutor into a ScheduledExecutorService that exits when the application is complete. It does so by using daemon threads and adding a shutdown hook to wait for their completion.

        This is mainly for fixed thread pools. See Executors.newScheduledThreadPool(int).

        Parameters:
        executor - the executor to modify to make sure it exits when the application is finished
        terminationTimeout - how long to wait for the executor to finish before terminating the JVM
        timeUnit - unit of time for the time parameter
        Returns:
        an unmodifiable version of the input which will not hang the JVM
      • getExitingScheduledExecutorService

        @Beta
        @GwtIncompatible
        public static ScheduledExecutorService getExitingScheduledExecutorService​(ScheduledThreadPoolExecutor executor)
        Converts the given ScheduledThreadPoolExecutor into a ScheduledExecutorService that exits when the application is complete. It does so by using daemon threads and adding a shutdown hook to wait for their completion.

        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).

        Parameters:
        executor - the executor to modify to make sure it exits when the application is finished
        Returns:
        an unmodifiable version of the input which will not hang the JVM
      • addDelayedShutdownHook

        @Beta
        @GwtIncompatible
        public static void addDelayedShutdownHook​(ExecutorService service,
                                                  Duration terminationTimeout)
        Add a shutdown hook to wait for thread completion in the given 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.
        Parameters:
        service - ExecutorService which uses daemon threads
        terminationTimeout - how long to wait for the executor to finish before terminating the JVM
        Since:
        28.0
      • addDelayedShutdownHook

        @Beta
        @GwtIncompatible
        public static void addDelayedShutdownHook​(ExecutorService service,
                                                  long terminationTimeout,
                                                  TimeUnit timeUnit)
        Add a shutdown hook to wait for thread completion in the given 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.
        Parameters:
        service - ExecutorService which uses daemon threads
        terminationTimeout - how long to wait for the executor to finish before terminating the JVM
        timeUnit - unit of time for the time parameter
      • newDirectExecutorService

        @GwtIncompatible
        public static ListeningExecutorService newDirectExecutorService()
        Creates an executor service that runs each task in the thread that invokes 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.

        Since:
        18.0 (present as MoreExecutors.sameThreadExecutor() since 10.0)
      • directExecutor

        public static Executor directExecutor()
        Returns an 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:

        • When a ListenableFuture listener is registered to run under directExecutor, the listener can execute in any of three possible threads:
          1. When a thread attaches a listener to a ListenableFuture that's already complete, the listener runs immediately in that thread.
          2. When a thread attaches a listener to a ListenableFuture that's incomplete and the ListenableFuture later completes normally, the listener runs in the thread that completes the ListenableFuture.
          3. When a listener is attached to a ListenableFuture and the ListenableFuture gets cancelled, the listener runs immediately in the thread that cancelled the Future.
          Given all these possibilities, it is frequently possible for listeners to execute in UI threads, RPC network threads, or other latency-sensitive threads. In those cases, slow listeners can harm responsiveness, slow the system as a whole, or worse. (See also the note about locking below.)
        • If many tasks will be triggered by the same event, one heavyweight task may delay other tasks -- even tasks that are not themselves directExecutor tasks.
        • If many such tasks are chained together (such as with 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.)
        • If an exception propagates out of a 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.
        A specific warning about locking: Code that executes user-supplied tasks, such as 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.

        Since:
        18.0
      • newSequentialExecutor

        @GwtIncompatible
        public static Executor newSequentialExecutor​(Executor delegate)
        Returns an 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:

        1. execution will not stop until the task queue is empty.
        2. tasks will begin execution with the thread marked as not interrupted - any interruption applies only to the task that was running at the point of interruption.
        3. if the thread was interrupted before the SequentialExecutor's worker begins execution, the interrupt will be restored to the thread after it completes so that its delegate Executor may process the interrupt.
        4. subtasks are run with the thread uninterrupted and interrupts received during execution of a task are ignored.

        RuntimeExceptions 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()).

        Since:
        23.3 (since 23.1 as sequentialExecutor)
      • listeningDecorator

        @GwtIncompatible
        public static ListeningExecutorService listeningDecorator​(ExecutorService delegate)
        Creates an 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.

        Since:
        10.0
      • listeningDecorator

        @GwtIncompatible
        public static ListeningScheduledExecutorService listeningDecorator​(ScheduledExecutorService delegate)
        Creates a 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.

        Since:
        10.0
      • shutdownAndAwaitTermination

        @Beta
        @CanIgnoreReturnValue
        @GwtIncompatible
        public static boolean shutdownAndAwaitTermination​(ExecutorService service,
                                                          Duration timeout)
        Shuts down the given executor service gradually, first disabling new submissions and later, if necessary, cancelling remaining tasks.

        The method takes the following steps:

        1. calls ExecutorService.shutdown(), disabling acceptance of new submitted tasks.
        2. awaits executor service termination for half of the specified timeout.
        3. if the timeout expires, it calls ExecutorService.shutdownNow(), cancelling pending tasks and interrupting running tasks.
        4. awaits executor service termination for the other half of the specified timeout.

        If, at any step of the process, the calling thread is interrupted, the method calls ExecutorService.shutdownNow() and returns.

        Parameters:
        service - the ExecutorService to shut down
        timeout - the maximum time to wait for the ExecutorService to terminate
        Returns:
        true if the ExecutorService was terminated successfully, false if the call timed out or was interrupted
        Since:
        28.0
      • shutdownAndAwaitTermination

        @Beta
        @CanIgnoreReturnValue
        @GwtIncompatible
        public static boolean shutdownAndAwaitTermination​(ExecutorService service,
                                                          long timeout,
                                                          TimeUnit unit)
        Shuts down the given executor service gradually, first disabling new submissions and later, if necessary, cancelling remaining tasks.

        The method takes the following steps:

        1. calls ExecutorService.shutdown(), disabling acceptance of new submitted tasks.
        2. awaits executor service termination for half of the specified timeout.
        3. if the timeout expires, it calls ExecutorService.shutdownNow(), cancelling pending tasks and interrupting running tasks.
        4. awaits executor service termination for the other half of the specified timeout.

        If, at any step of the process, the calling thread is interrupted, the method calls ExecutorService.shutdownNow() and returns.

        Parameters:
        service - the ExecutorService to shut down
        timeout - the maximum time to wait for the ExecutorService to terminate
        unit - the time unit of the timeout argument
        Returns:
        true if the ExecutorService was terminated successfully, false if the call timed out or was interrupted
        Since:
        17.0