001    /*
002     * Copyright (C) 2007 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.util.concurrent;
018    
019    import static com.google.common.base.Preconditions.checkArgument;
020    import static com.google.common.base.Preconditions.checkNotNull;
021    
022    import com.google.common.annotations.Beta;
023    import com.google.common.collect.Lists;
024    import com.google.common.collect.Queues;
025    
026    import java.util.Collection;
027    import java.util.Collections;
028    import java.util.Iterator;
029    import java.util.List;
030    import java.util.concurrent.BlockingQueue;
031    import java.util.concurrent.Callable;
032    import java.util.concurrent.ExecutionException;
033    import java.util.concurrent.ExecutorService;
034    import java.util.concurrent.Executors;
035    import java.util.concurrent.Future;
036    import java.util.concurrent.RejectedExecutionException;
037    import java.util.concurrent.ScheduledExecutorService;
038    import java.util.concurrent.ScheduledFuture;
039    import java.util.concurrent.ScheduledThreadPoolExecutor;
040    import java.util.concurrent.ThreadFactory;
041    import java.util.concurrent.ThreadPoolExecutor;
042    import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
043    import java.util.concurrent.TimeUnit;
044    import java.util.concurrent.TimeoutException;
045    import java.util.concurrent.locks.Condition;
046    import java.util.concurrent.locks.Lock;
047    import java.util.concurrent.locks.ReentrantLock;
048    
049    /**
050     * Factory and utility methods for {@link java.util.concurrent.Executor}, {@link
051     * ExecutorService}, and {@link ThreadFactory}.
052     *
053     * @author Eric Fellheimer
054     * @author Kyle Littlefield
055     * @author Justin Mahoney
056     * @since 3.0
057     */
058    public final class MoreExecutors {
059      private MoreExecutors() {}
060    
061      /**
062       * Converts the given ThreadPoolExecutor into an ExecutorService that exits
063       * when the application is complete.  It does so by using daemon threads and
064       * adding a shutdown hook to wait for their completion.
065       *
066       * <p>This is mainly for fixed thread pools.
067       * See {@link Executors#newFixedThreadPool(int)}.
068       *
069       * @param executor the executor to modify to make sure it exits when the
070       *        application is finished
071       * @param terminationTimeout how long to wait for the executor to
072       *        finish before terminating the JVM
073       * @param timeUnit unit of time for the time parameter
074       * @return an unmodifiable version of the input which will not hang the JVM
075       */
076      @Beta
077      public static ExecutorService getExitingExecutorService(
078          ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
079        executor.setThreadFactory(new ThreadFactoryBuilder()
080            .setDaemon(true)
081            .setThreadFactory(executor.getThreadFactory())
082            .build());
083    
084        ExecutorService service = Executors.unconfigurableExecutorService(executor);
085    
086        addDelayedShutdownHook(service, terminationTimeout, timeUnit);
087    
088        return service;
089      }
090    
091      /**
092       * Converts the given ScheduledThreadPoolExecutor into a
093       * ScheduledExecutorService that exits when the application is complete.  It
094       * does so by using daemon threads and adding a shutdown hook to wait for
095       * their completion.
096       *
097       * <p>This is mainly for fixed thread pools.
098       * See {@link Executors#newScheduledThreadPool(int)}.
099       *
100       * @param executor the executor to modify to make sure it exits when the
101       *        application is finished
102       * @param terminationTimeout how long to wait for the executor to
103       *        finish before terminating the JVM
104       * @param timeUnit unit of time for the time parameter
105       * @return an unmodifiable version of the input which will not hang the JVM
106       */
107      @Beta
108      public static ScheduledExecutorService getExitingScheduledExecutorService(
109          ScheduledThreadPoolExecutor executor, long terminationTimeout,
110          TimeUnit timeUnit) {
111        executor.setThreadFactory(new ThreadFactoryBuilder()
112            .setDaemon(true)
113            .setThreadFactory(executor.getThreadFactory())
114            .build());
115    
116        ScheduledExecutorService service =
117            Executors.unconfigurableScheduledExecutorService(executor);
118    
119        addDelayedShutdownHook(service, terminationTimeout, timeUnit);
120    
121        return service;
122      }
123    
124      /**
125       * Add a shutdown hook to wait for thread completion in the given
126       * {@link ExecutorService service}.  This is useful if the given service uses
127       * daemon threads, and we want to keep the JVM from exiting immediately on
128       * shutdown, instead giving these daemon threads a chance to terminate
129       * normally.
130       * @param service ExecutorService which uses daemon threads
131       * @param terminationTimeout how long to wait for the executor to finish
132       *        before terminating the JVM
133       * @param timeUnit unit of time for the time parameter
134       */
135      @Beta
136      public static void addDelayedShutdownHook(
137          final ExecutorService service, final long terminationTimeout,
138          final TimeUnit timeUnit) {
139        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
140          public void run() {
141            try {
142              // We'd like to log progress and failures that may arise in the
143              // following code, but unfortunately the behavior of logging
144              // is undefined in shutdown hooks.
145              // This is because the logging code installs a shutdown hook of its
146              // own. See Cleaner class inside {@link LogManager}.
147              service.shutdown();
148              service.awaitTermination(terminationTimeout, timeUnit);
149            } catch (InterruptedException ignored) {
150              // We're shutting down anyway, so just ignore.
151            }
152          }
153        }, "DelayedShutdownHook-for-" + service));
154      }
155    
156      /**
157       * Converts the given ThreadPoolExecutor into an ExecutorService that exits
158       * when the application is complete.  It does so by using daemon threads and
159       * adding a shutdown hook to wait for their completion.
160       *
161       * <p>This method waits 120 seconds before continuing with JVM termination,
162       * even if the executor has not finished its work.
163       *
164       * <p>This is mainly for fixed thread pools.
165       * See {@link Executors#newFixedThreadPool(int)}.
166       *
167       * @param executor the executor to modify to make sure it exits when the
168       *        application is finished
169       * @return an unmodifiable version of the input which will not hang the JVM
170       */
171      @Beta
172      public static ExecutorService getExitingExecutorService(
173          ThreadPoolExecutor executor) {
174        return getExitingExecutorService(executor, 120, TimeUnit.SECONDS);
175      }
176    
177      /**
178       * Converts the given ThreadPoolExecutor into a ScheduledExecutorService that
179       * exits when the application is complete.  It does so by using daemon threads
180       * and adding a shutdown hook to wait for their completion.
181       *
182       * <p>This method waits 120 seconds before continuing with JVM termination,
183       * even if the executor has not finished its work.
184       *
185       * <p>This is mainly for fixed thread pools.
186       * See {@link Executors#newScheduledThreadPool(int)}.
187       *
188       * @param executor the executor to modify to make sure it exits when the
189       *        application is finished
190       * @return an unmodifiable version of the input which will not hang the JVM
191       */
192      @Beta
193      public static ScheduledExecutorService getExitingScheduledExecutorService(
194          ScheduledThreadPoolExecutor executor) {
195        return getExitingScheduledExecutorService(executor, 120, TimeUnit.SECONDS);
196      }
197    
198      /**
199       * Creates an executor service that runs each task in the thread
200       * that invokes {@code execute/submit}, as in {@link CallerRunsPolicy}  This
201       * applies both to individually submitted tasks and to collections of tasks
202       * submitted via {@code invokeAll} or {@code invokeAny}.  In the latter case,
203       * tasks will run serially on the calling thread.  Tasks are run to
204       * completion before a {@code Future} is returned to the caller (unless the
205       * executor has been shutdown).
206       *
207       * <p>Although all tasks are immediately executed in the thread that
208       * submitted the task, this {@code ExecutorService} imposes a small
209       * locking overhead on each task submission in order to implement shutdown
210       * and termination behavior.
211       *
212       * <p>The implementation deviates from the {@code ExecutorService}
213       * specification with regards to the {@code shutdownNow} method.  First,
214       * "best-effort" with regards to canceling running tasks is implemented
215       * as "no-effort".  No interrupts or other attempts are made to stop
216       * threads executing tasks.  Second, the returned list will always be empty,
217       * as any submitted task is considered to have started execution.
218       * This applies also to tasks given to {@code invokeAll} or {@code invokeAny}
219       * which are pending serial execution, even the subset of the tasks that
220       * have not yet started execution.  It is unclear from the
221       * {@code ExecutorService} specification if these should be included, and
222       * it's much easier to implement the interpretation that they not be.
223       * Finally, a call to {@code shutdown} or {@code shutdownNow} may result
224       * in concurrent calls to {@code invokeAll/invokeAny} throwing
225       * RejectedExecutionException, although a subset of the tasks may already
226       * have been executed.
227       *
228       * @since 10.0 (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
229       *        >mostly source-compatible</a> since 3.0)
230       */
231      public static ListeningExecutorService sameThreadExecutor() {
232        return new SameThreadExecutorService();
233      }
234    
235      // See sameThreadExecutor javadoc for behavioral notes.
236      private static class SameThreadExecutorService
237          extends AbstractListeningExecutorService {
238        /**
239         * Lock used whenever accessing the state variables
240         * (runningTasks, shutdown, terminationCondition) of the executor
241         */
242        private final Lock lock = new ReentrantLock();
243    
244        /** Signaled after the executor is shutdown and running tasks are done */
245        private final Condition termination = lock.newCondition();
246    
247        /*
248         * Conceptually, these two variables describe the executor being in
249         * one of three states:
250         *   - Active: shutdown == false
251         *   - Shutdown: runningTasks > 0 and shutdown == true
252         *   - Terminated: runningTasks == 0 and shutdown == true
253         */
254        private int runningTasks = 0;
255        private boolean shutdown = false;
256    
257        public void execute(Runnable command) {
258          startTask();
259          try {
260            command.run();
261          } finally {
262            endTask();
263          }
264        }
265    
266        public boolean isShutdown() {
267          lock.lock();
268          try {
269            return shutdown;
270          } finally {
271            lock.unlock();
272          }
273        }
274    
275        public void shutdown() {
276          lock.lock();
277          try {
278            shutdown = true;
279          } finally {
280            lock.unlock();
281          }
282        }
283    
284        // See sameThreadExecutor javadoc for unusual behavior of this method.
285        public List<Runnable> shutdownNow() {
286          shutdown();
287          return Collections.emptyList();
288        }
289    
290        public boolean isTerminated() {
291          lock.lock();
292          try {
293            return shutdown && runningTasks == 0;
294          } finally {
295            lock.unlock();
296          }
297        }
298    
299        public boolean awaitTermination(long timeout, TimeUnit unit)
300            throws InterruptedException {
301          long nanos = unit.toNanos(timeout);
302          lock.lock();
303          try {
304            for (;;) {
305              if (isTerminated()) {
306                return true;
307              } else if (nanos <= 0) {
308                return false;
309              } else {
310                nanos = termination.awaitNanos(nanos);
311              }
312            }
313          } finally {
314            lock.unlock();
315          }
316        }
317    
318        /**
319         * Checks if the executor has been shut down and increments the running
320         * task count.
321         *
322         * @throws RejectedExecutionException if the executor has been previously
323         *         shutdown
324         */
325        private void startTask() {
326          lock.lock();
327          try {
328            if (isShutdown()) {
329              throw new RejectedExecutionException("Executor already shutdown");
330            }
331            runningTasks++;
332          } finally {
333            lock.unlock();
334          }
335        }
336    
337        /**
338         * Decrements the running task count.
339         */
340        private void endTask() {
341          lock.lock();
342          try {
343            runningTasks--;
344            if (isTerminated()) {
345              termination.signalAll();
346            }
347          } finally {
348            lock.unlock();
349          }
350        }
351      }
352    
353      /**
354       * Creates an {@link ExecutorService} whose {@code submit} and {@code
355       * invokeAll} methods submit {@link ListenableFutureTask} instances to the
356       * given delegate executor. Those methods, as well as {@code execute} and
357       * {@code invokeAny}, are implemented in terms of calls to {@code
358       * delegate.execute}. All other methods are forwarded unchanged to the
359       * delegate. This implies that the returned {@code ListeningExecutorService}
360       * never calls the delegate's {@code submit}, {@code invokeAll}, and {@code
361       * invokeAny} methods, so any special handling of tasks must be implemented in
362       * the delegate's {@code execute} method or by wrapping the returned {@code
363       * ListeningExecutorService}.
364       *
365       * <p>If the delegate executor was already an instance of {@code
366       * ListeningExecutorService}, it is returned untouched, and the rest of this
367       * documentation does not apply.
368       *
369       * @since 10.0
370       */
371      public static ListeningExecutorService listeningDecorator(
372          ExecutorService delegate) {
373        return (delegate instanceof ListeningExecutorService)
374            ? (ListeningExecutorService) delegate
375            : (delegate instanceof ScheduledExecutorService)
376            ? new ScheduledListeningDecorator((ScheduledExecutorService) delegate)
377            : new ListeningDecorator(delegate);
378      }
379    
380      /**
381       * Creates a {@link ScheduledExecutorService} whose {@code submit} and {@code
382       * invokeAll} methods submit {@link ListenableFutureTask} instances to the
383       * given delegate executor. Those methods, as well as {@code execute} and
384       * {@code invokeAny}, are implemented in terms of calls to {@code
385       * delegate.execute}. All other methods are forwarded unchanged to the
386       * delegate. This implies that the returned {@code
387       * SchedulingListeningExecutorService} never calls the delegate's {@code
388       * submit}, {@code invokeAll}, and {@code invokeAny} methods, so any special
389       * handling of tasks must be implemented in the delegate's {@code execute}
390       * method or by wrapping the returned {@code
391       * SchedulingListeningExecutorService}.
392       *
393       * <p>If the delegate executor was already an instance of {@code
394       * ListeningScheduledExecutorService}, it is returned untouched, and the rest
395       * of this documentation does not apply.
396       *
397       * @since 10.0
398       */
399      public static ListeningScheduledExecutorService listeningDecorator(
400          ScheduledExecutorService delegate) {
401        return (delegate instanceof ListeningScheduledExecutorService)
402            ? (ListeningScheduledExecutorService) delegate
403            : new ScheduledListeningDecorator(delegate);
404      }
405    
406      private static class ListeningDecorator
407          extends AbstractListeningExecutorService {
408        final ExecutorService delegate;
409    
410        ListeningDecorator(ExecutorService delegate) {
411          this.delegate = checkNotNull(delegate);
412        }
413    
414        public boolean awaitTermination(long timeout, TimeUnit unit)
415            throws InterruptedException {
416          return delegate.awaitTermination(timeout, unit);
417        }
418    
419        public boolean isShutdown() {
420          return delegate.isShutdown();
421        }
422    
423        public boolean isTerminated() {
424          return delegate.isTerminated();
425        }
426    
427        public void shutdown() {
428          delegate.shutdown();
429        }
430    
431        public List<Runnable> shutdownNow() {
432          return delegate.shutdownNow();
433        }
434    
435        public void execute(Runnable command) {
436          delegate.execute(command);
437        }
438      }
439    
440      private static class ScheduledListeningDecorator
441          extends ListeningDecorator implements ListeningScheduledExecutorService {
442        @SuppressWarnings("hiding")
443        final ScheduledExecutorService delegate;
444    
445        ScheduledListeningDecorator(ScheduledExecutorService delegate) {
446          super(delegate);
447          this.delegate = checkNotNull(delegate);
448        }
449    
450        public ScheduledFuture<?> schedule(
451            Runnable command, long delay, TimeUnit unit) {
452          return delegate.schedule(command, delay, unit);
453        }
454    
455        public <V> ScheduledFuture<V> schedule(
456            Callable<V> callable, long delay, TimeUnit unit) {
457          return delegate.schedule(callable, delay, unit);
458        }
459    
460        public ScheduledFuture<?> scheduleAtFixedRate(
461            Runnable command, long initialDelay, long period, TimeUnit unit) {
462          return delegate.scheduleAtFixedRate(command, initialDelay, period, unit);
463        }
464    
465        public ScheduledFuture<?> scheduleWithFixedDelay(
466            Runnable command, long initialDelay, long delay, TimeUnit unit) {
467          return delegate.scheduleWithFixedDelay(
468              command, initialDelay, delay, unit);
469        }
470      }
471    
472      /*
473       * This following method is a modified version of one found in
474       * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck/AbstractExecutorServiceTest.java?revision=1.30
475       * which contained the following notice:
476       *
477       * Written by Doug Lea with assistance from members of JCP JSR-166
478       * Expert Group and released to the public domain, as explained at
479       * http://creativecommons.org/publicdomain/zero/1.0/
480       * Other contributors include Andrew Wright, Jeffrey Hayes,
481       * Pat Fisher, Mike Judd.
482       */
483    
484      /**
485       * An implementation of {@link ExecutorService#invokeAny} for {@link ListeningExecutorService}
486       * implementations.
487       */ static <T> T invokeAnyImpl(ListeningExecutorService executorService,
488          Collection<? extends Callable<T>> tasks, boolean timed, long nanos)
489              throws InterruptedException, ExecutionException, TimeoutException {
490        int ntasks = tasks.size();
491        checkArgument(ntasks > 0);
492        List<Future<T>> futures = Lists.newArrayListWithCapacity(ntasks);
493        BlockingQueue<Future<T>> futureQueue = Queues.newLinkedBlockingQueue();
494    
495        // For efficiency, especially in executors with limited
496        // parallelism, check to see if previously submitted tasks are
497        // done before submitting more of them. This interleaving
498        // plus the exception mechanics account for messiness of main
499        // loop.
500    
501        try {
502          // Record exceptions so that if we fail to obtain any
503          // result, we can throw the last exception we got.
504          ExecutionException ee = null;
505          long lastTime = timed ? System.nanoTime() : 0;
506          Iterator<? extends Callable<T>> it = tasks.iterator();
507    
508          futures.add(submitAndAddQueueListener(executorService, it.next(), futureQueue));
509          --ntasks;
510          int active = 1;
511    
512          for (;;) {
513            Future<T> f = futureQueue.poll();
514            if (f == null) {
515              if (ntasks > 0) {
516                --ntasks;
517                futures.add(submitAndAddQueueListener(executorService, it.next(), futureQueue));
518                ++active;
519              } else if (active == 0) {
520                break;
521              } else if (timed) {
522                f = futureQueue.poll(nanos, TimeUnit.NANOSECONDS);
523                if (f == null) {
524                  throw new TimeoutException();
525                }
526                long now = System.nanoTime();
527                nanos -= now - lastTime;
528                lastTime = now;
529              } else {
530                f = futureQueue.take();
531              }
532            }
533            if (f != null) {
534              --active;
535              try {
536                return f.get();
537              } catch (ExecutionException eex) {
538                ee = eex;
539              } catch (RuntimeException rex) {
540                ee = new ExecutionException(rex);
541              }
542            }
543          }
544    
545          if (ee == null) {
546            ee = new ExecutionException(null);
547          }
548          throw ee;
549        } finally {
550          for (Future<T> f : futures) {
551            f.cancel(true);
552          }
553        }
554      }
555    
556      /**
557       * Submits the task and adds a listener that adds the future to {@code queue} when it completes.
558       */
559      private static <T> ListenableFuture<T> submitAndAddQueueListener(
560          ListeningExecutorService executorService, Callable<T> task,
561          final BlockingQueue<Future<T>> queue) {
562        final ListenableFuture<T> future = executorService.submit(task);
563        future.addListener(new Runnable() {
564          public void run() {
565            queue.add(future);
566          }
567        }, MoreExecutors.sameThreadExecutor());
568        return future;
569      }
570    }