content: /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  /*
   * This file is available under and governed by the GNU General Public
   * License version 2 only, as published by the Free Software Foundation.
   * However, the following notice accompanied the original version of this
   * file:
   *
   * Written by Doug Lea with assistance from members of JCP JSR-166
   * Expert Group and released to the public domain, as explained at
   * http://creativecommons.org/publicdomain/zero/1.0/
   */
  
  package java.util.concurrent;
  
  import dalvik.annotation.optimization.ReachabilitySensitive;
  
  import java.security.AccessControlContext;
  import java.security.AccessControlException;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  import java.security.PrivilegedActionException;
  import java.security.PrivilegedExceptionAction;
  import java.util.Collection;
  import java.util.List;
  import java.util.concurrent.atomic.AtomicInteger;
  
  import sun.security.util.SecurityConstants;
  
  // BEGIN android-note
  // removed security manager docs
  // END android-note
  
  /**
   * Factory and utility methods for {@link Executor}, {@link
   * ExecutorService}, {@link ScheduledExecutorService}, {@link
   * ThreadFactory}, and {@link Callable} classes defined in this
   * package. This class supports the following kinds of methods:
   *
   * <ul>
   *   <li>Methods that create and return an {@link ExecutorService}
   *       set up with commonly useful configuration settings.
   *   <li>Methods that create and return a {@link ScheduledExecutorService}
   *       set up with commonly useful configuration settings.
   *   <li>Methods that create and return a "wrapped" ExecutorService, that
   *       disables reconfiguration by making implementation-specific methods
   *       inaccessible.
   *   <li>Methods that create and return a {@link ThreadFactory}
   *       that sets newly created threads to a known state.
   *   <li>Methods that create and return a {@link Callable}
   *       out of other closure-like forms, so they can be used
   *       in execution methods requiring {@code Callable}.
   * </ul>
   *
   * @author Doug Lea
   * @since 1.5
   */
  public class Executors {
  
      /**
       * Creates a thread pool that reuses a fixed number of threads
       * operating off a shared unbounded queue.  At any point, at most
       * {@code nThreads} threads will be active processing tasks.
       * If additional tasks are submitted when all threads are active,
       * they will wait in the queue until a thread is available.
       * If any thread terminates due to a failure during execution
       * prior to shutdown, a new one will take its place if needed to
       * execute subsequent tasks.  The threads in the pool will exist
       * until it is explicitly {@link ExecutorService#shutdown shutdown}.
       *
       * @param nThreads the number of threads in the pool
       * @return the newly created thread pool
       * @throws IllegalArgumentException if {@code nThreads <= 0}
       * 核心线程数为n，最大线程数为n。
       * 使用场景：明确同时执行任务数量时。
       */
      public static ExecutorService newFixedThreadPool(int nThreads) {
          //自己设计核心线程的数量，非核心线程为0
          //当小于核心线程的时候会创建核心来执行任务。
          //当大于等于核心线程的时候会将任务加入到workQueue中，由于这个queue无限大，所以可以一直加
          //假如加的超过workQueue的话，就会拒绝任务
          return new ThreadPoolExecutor(nThreads, nThreads,
                  0L, TimeUnit.MILLISECONDS,
                  new LinkedBlockingQueue<Runnable>());
      }
  
      /**
       * Creates a thread pool that maintains enough threads to support
       * the given parallelism level, and may use multiple queues to
       * reduce contention. The parallelism level corresponds to the
       * maximum number of threads actively engaged in, or available to
       * engage in, task processing. The actual number of threads may
       * grow and shrink dynamically. A work-stealing pool makes no
       * guarantees about the order in which submitted tasks are
       * executed.
       *
       * @param parallelism the targeted parallelism level
       * @return the newly created thread pool
       * @throws IllegalArgumentException if {@code parallelism <= 0}
       * @since 1.8
       */
      public static ExecutorService newWorkStealingPool(int parallelism) {
          return new ForkJoinPool
                  (parallelism,
                          ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                          null, true);
      }
  
      /**
       * Creates a work-stealing thread pool using the number of
       * {@linkplain Runtime#availableProcessors available processors}
       * as its target parallelism level.
       *
       * @return the newly created thread pool
       * @see #newWorkStealingPool(int)
       * @since 1.8
       */
      public static ExecutorService newWorkStealingPool() {
          return new ForkJoinPool
                  (Runtime.getRuntime().availableProcessors(),
                          ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                          null, true);
      }
  
      /**
       * Creates a thread pool that reuses a fixed number of threads
       * operating off a shared unbounded queue, using the provided
       * ThreadFactory to create new threads when needed.  At any point,
       * at most {@code nThreads} threads will be active processing
       * tasks.  If additional tasks are submitted when all threads are
       * active, they will wait in the queue until a thread is
       * available.  If any thread terminates due to a failure during
       * execution prior to shutdown, a new one will take its place if
       * needed to execute subsequent tasks.  The threads in the pool will
       * exist until it is explicitly {@link ExecutorService#shutdown
       * shutdown}.
       *
       * @param nThreads      the number of threads in the pool
       * @param threadFactory the factory to use when creating new threads
       * @return the newly created thread pool
       * @throws NullPointerException     if threadFactory is null
       * @throws IllegalArgumentException if {@code nThreads <= 0}
       */
      public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
          return new ThreadPoolExecutor(nThreads, nThreads,
                  0L, TimeUnit.MILLISECONDS,
                  new LinkedBlockingQueue<Runnable>(),
                  threadFactory);
      }
  
      /**
       * Creates an Executor that uses a single worker thread operating
       * off an unbounded queue. (Note however that if this single
       * thread terminates due to a failure during execution prior to
       * shutdown, a new one will take its place if needed to execute
       * subsequent tasks.)  Tasks are guaranteed to execute
       * sequentially, and no more than one task will be active at any
       * given time. Unlike the otherwise equivalent
       * {@code newFixedThreadPool(1)} the returned executor is
       * guaranteed not to be reconfigurable to use additional threads.
       *
       * @return the newly created single-threaded Executor
       * 核心线程数为1，最大线程数为1，也就是说SingleThreadExecutor这个线程池中的线程数固定为1。
       * 使用场景：当多个任务都需要访问同一个资源的时候。
       */
      public static ExecutorService newSingleThreadExecutor() {
          //核心线程永远只有一个，当超过一个核心线程后，会将任务加入到队列中，这个队列无限大
          //如果真的超过了这个队列的话，任务会被拒绝
          return new FinalizableDelegatedExecutorService
                  (new ThreadPoolExecutor(1, 1,
                          0L, TimeUnit.MILLISECONDS,
                          //queue的最大值为 Integer.MAX_VALUE
                          new LinkedBlockingQueue<Runnable>()));
      }
  
      /**
       * Creates an Executor that uses a single worker thread operating
       * off an unbounded queue, and uses the provided ThreadFactory to
       * create a new thread when needed. Unlike the otherwise
       * equivalent {@code newFixedThreadPool(1, threadFactory)} the
       * returned executor is guaranteed not to be reconfigurable to use
       * additional threads.
       *
       * @param threadFactory the factory to use when creating new
       *                      threads
       * @return the newly created single-threaded Executor
       * @throws NullPointerException if threadFactory is null
       */
      public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
          return new FinalizableDelegatedExecutorService
                  (new ThreadPoolExecutor(1, 1,
                          0L, TimeUnit.MILLISECONDS,
                          new LinkedBlockingQueue<Runnable>(),
                          threadFactory));
      }
  
      /**
       * Creates a thread pool that creates new threads as needed, but
       * will reuse previously constructed threads when they are
       * available.  These pools will typically improve the performance
       * of programs that execute many short-lived asynchronous tasks.
       * Calls to {@code execute} will reuse previously constructed
       * threads if available. If no existing thread is available, a new
       * thread will be created and added to the pool. Threads that have
       * not been used for sixty seconds are terminated and removed from
       * the cache. Thus, a pool that remains idle for long enough will
       * not consume any resources. Note that pools with similar
       * properties but different details (for example, timeout parameters)
       * may be created using {@link ThreadPoolExecutor} constructors.
       *
       * @return the newly created thread pool
       * 核心线程数为0，最大线程数无上限，线程超时时间60秒。
       * 使用场景：处理大量耗时较短的任务。
       */
      public static ExecutorService newCachedThreadPool() {
          //核心线程为0，也就是有新任务就会大于核心线程。
          //workQueue是SynchronousQueue，它的容量为0，也就是加入队列会失败。
          //由于非核心线程无限大，所以会创建核心线程，将任务放到非核心线程中执行
          //由于是非核心线程，当线程闲置的时候，60s后会自动销毁
          return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                  60L, TimeUnit.SECONDS,
                  new SynchronousQueue<Runnable>());
      }
  
      /**
       * Creates a thread pool that creates new threads as needed, but
       * will reuse previously constructed threads when they are
       * available, and uses the provided
       * ThreadFactory to create new threads when needed.
       *
       * @param threadFactory the factory to use when creating new threads
       * @return the newly created thread pool
       * @throws NullPointerException if threadFactory is null
       */
      public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
          return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                  60L, TimeUnit.SECONDS,
                  new SynchronousQueue<Runnable>(),
                  threadFactory);
      }
  
      /**
       * Creates a single-threaded executor that can schedule commands
       * to run after a given delay, or to execute periodically.
       * (Note however that if this single
       * thread terminates due to a failure during execution prior to
       * shutdown, a new one will take its place if needed to execute
       * subsequent tasks.)  Tasks are guaranteed to execute
       * sequentially, and no more than one task will be active at any
       * given time. Unlike the otherwise equivalent
       * {@code newScheduledThreadPool(1)} the returned executor is
       * guaranteed not to be reconfigurable to use additional threads.
       *
       * @return the newly created scheduled executor
       */
      public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
          return new DelegatedScheduledExecutorService
                  (new ScheduledThreadPoolExecutor(1));
      }
  
      /**
       * Creates a single-threaded executor that can schedule commands
       * to run after a given delay, or to execute periodically.  (Note
       * however that if this single thread terminates due to a failure
       * during execution prior to shutdown, a new one will take its
       * place if needed to execute subsequent tasks.)  Tasks are
       * guaranteed to execute sequentially, and no more than one task
       * will be active at any given time. Unlike the otherwise
       * equivalent {@code newScheduledThreadPool(1, threadFactory)}
       * the returned executor is guaranteed not to be reconfigurable to
       * use additional threads.
       *
       * @param threadFactory the factory to use when creating new
       *                      threads
       * @return a newly created scheduled executor
       * @throws NullPointerException if threadFactory is null
       */
      public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
          return new DelegatedScheduledExecutorService
                  (new ScheduledThreadPoolExecutor(1, threadFactory));
      }
  
      /**
       * Creates a thread pool that can schedule commands to run after a
       * given delay, or to execute periodically.
       *
       * @param corePoolSize the number of threads to keep in the pool,
       *                     even if they are idle
       * @return a newly created scheduled thread pool
       * @throws IllegalArgumentException if {@code corePoolSize < 0}
       * 核心线程数自定，最大线程数无上限。
       * 使用场景：处理延时任务。
       */
      public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
          return new ScheduledThreadPoolExecutor(corePoolSize);
      }
  
      /**
       * Creates a thread pool that can schedule commands to run after a
       * given delay, or to execute periodically.
       *
       * @param corePoolSize  the number of threads to keep in the pool,
       *                      even if they are idle
       * @param threadFactory the factory to use when the executor
       *                      creates a new thread
       * @return a newly created scheduled thread pool
       * @throws IllegalArgumentException if {@code corePoolSize < 0}
       * @throws NullPointerException     if threadFactory is null
       */
      public static ScheduledExecutorService newScheduledThreadPool(
              int corePoolSize, ThreadFactory threadFactory) {
          return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
      }
  
      /**
       * Returns an object that delegates all defined {@link
       * ExecutorService} methods to the given executor, but not any
       * other methods that might otherwise be accessible using
       * casts. This provides a way to safely "freeze" configuration and
       * disallow tuning of a given concrete implementation.
       *
       * @param executor the underlying implementation
       * @return an {@code ExecutorService} instance
       * @throws NullPointerException if executor null
       */
      public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
          if (executor == null)
              throw new NullPointerException();
          return new DelegatedExecutorService(executor);
      }
  
      /**
       * Returns an object that delegates all defined {@link
       * ScheduledExecutorService} methods to the given executor, but
       * not any other methods that might otherwise be accessible using
       * casts. This provides a way to safely "freeze" configuration and
       * disallow tuning of a given concrete implementation.
       *
       * @param executor the underlying implementation
       * @return a {@code ScheduledExecutorService} instance
       * @throws NullPointerException if executor null
       */
      public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
          if (executor == null)
              throw new NullPointerException();
          return new DelegatedScheduledExecutorService(executor);
      }
  
      // Android-changed: Removed references to SecurityManager from javadoc.
  
      /**
       * Returns a default thread factory used to create new threads.
       * This factory creates all new threads used by an Executor in the
       * same {@link ThreadGroup}. Each new
       * thread is created as a non-daemon thread with priority set to
       * the smaller of {@code Thread.NORM_PRIORITY} and the maximum
       * priority permitted in the thread group.  New threads have names
       * accessible via {@link Thread#getName} of
       * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
       * number of this factory, and <em>M</em> is the sequence number
       * of the thread created by this factory.
       *
       * @return a thread factory
       */
      public static ThreadFactory defaultThreadFactory() {
          return new DefaultThreadFactory();
      }
  
      // Android-changed: Dropped documentation for legacy security code.
  
      /**
       * Legacy security code; do not use.
       */
      public static ThreadFactory privilegedThreadFactory() {
          return new PrivilegedThreadFactory();
      }
  
      /**
       * Returns a {@link Callable} object that, when
       * called, runs the given task and returns the given result.  This
       * can be useful when applying methods requiring a
       * {@code Callable} to an otherwise resultless action.
       *
       * @param task   the task to run
       * @param result the result to return
       * @param <T>    the type of the result
       * @return a callable object
       * @throws NullPointerException if task null
       */
      public static <T> Callable<T> callable(Runnable task, T result) {
          if (task == null)
              throw new NullPointerException();
          return new RunnableAdapter<T>(task, result);
      }
  
      /**
       * Returns a {@link Callable} object that, when
       * called, runs the given task and returns {@code null}.
       *
       * @param task the task to run
       * @return a callable object
       * @throws NullPointerException if task null
       */
      public static Callable<Object> callable(Runnable task) {
          if (task == null)
              throw new NullPointerException();
          return new RunnableAdapter<Object>(task, null);
      }
  
      /**
       * Returns a {@link Callable} object that, when
       * called, runs the given privileged action and returns its result.
       *
       * @param action the privileged action to run
       * @return a callable object
       * @throws NullPointerException if action null
       */
      public static Callable<Object> callable(final PrivilegedAction<?> action) {
          if (action == null)
              throw new NullPointerException();
          return new Callable<Object>() {
              public Object call() {
                  return action.run();
              }
          };
      }
  
      /**
       * Returns a {@link Callable} object that, when
       * called, runs the given privileged exception action and returns
       * its result.
       *
       * @param action the privileged exception action to run
       * @return a callable object
       * @throws NullPointerException if action null
       */
      public static Callable<Object> callable(final PrivilegedExceptionAction<?> action) {
          if (action == null)
              throw new NullPointerException();
          return new Callable<Object>() {
              public Object call() throws Exception {
                  return action.run();
              }
          };
      }
  
      // Android-changed: Dropped documentation for legacy security code.
  
      /**
       * Legacy security code; do not use.
       */
      public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
          if (callable == null)
              throw new NullPointerException();
          return new PrivilegedCallable<T>(callable);
      }
  
      // Android-changed: Dropped documentation for legacy security code.
  
      /**
       * Legacy security code; do not use.
       */
      public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
          if (callable == null)
              throw new NullPointerException();
          return new PrivilegedCallableUsingCurrentClassLoader<T>(callable);
      }
  
      // Non-public classes supporting the public methods
  
      /**
       * A callable that runs given task and returns given result.
       */
      private static final class RunnableAdapter<T> implements Callable<T> {
          private final Runnable task;
          private final T result;
  
          RunnableAdapter(Runnable task, T result) {
              this.task = task;
              this.result = result;
          }
  
          public T call() {
              task.run();
              return result;
          }
      }
  
      /**
       * A callable that runs under established access control settings.
       */
      private static final class PrivilegedCallable<T> implements Callable<T> {
          final Callable<T> task;
          final AccessControlContext acc;
  
          PrivilegedCallable(Callable<T> task) {
              this.task = task;
              this.acc = AccessController.getContext();
          }
  
          public T call() throws Exception {
              try {
                  return AccessController.doPrivileged(
                          new PrivilegedExceptionAction<T>() {
                              public T run() throws Exception {
                                  return task.call();
                              }
                          }, acc);
              } catch (PrivilegedActionException e) {
                  throw e.getException();
              }
          }
      }
  
      /**
       * A callable that runs under established access control settings and
       * current ClassLoader.
       */
      private static final class PrivilegedCallableUsingCurrentClassLoader<T>
              implements Callable<T> {
          final Callable<T> task;
          final AccessControlContext acc;
          final ClassLoader ccl;
  
          PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
              // Android-removed: System.getSecurityManager always returns null.
              /*
              SecurityManager sm = System.getSecurityManager();
              if (sm != null) {
                  // Calls to getContextClassLoader from this class
                  // never trigger a security check, but we check
                  // whether our callers have this permission anyways.
                  sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
  
                  // Whether setContextClassLoader turns out to be necessary
                  // or not, we fail fast if permission is not available.
                  sm.checkPermission(new RuntimePermission("setContextClassLoader"));
              }
              */
              this.task = task;
              this.acc = AccessController.getContext();
              this.ccl = Thread.currentThread().getContextClassLoader();
          }
  
          public T call() throws Exception {
              try {
                  return AccessController.doPrivileged(
                          new PrivilegedExceptionAction<T>() {
                              public T run() throws Exception {
                                  Thread t = Thread.currentThread();
                                  ClassLoader cl = t.getContextClassLoader();
                                  if (ccl == cl) {
                                      return task.call();
                                  } else {
                                      t.setContextClassLoader(ccl);
                                      try {
                                          return task.call();
                                      } finally {
                                          t.setContextClassLoader(cl);
                                      }
                                  }
                              }
                          }, acc);
              } catch (PrivilegedActionException e) {
                  throw e.getException();
              }
          }
      }
  
      /**
       * The default thread factory.
       */
      private static class DefaultThreadFactory implements ThreadFactory {
          private static final AtomicInteger poolNumber = new AtomicInteger(1);
          private final ThreadGroup group;
          private final AtomicInteger threadNumber = new AtomicInteger(1);
          private final String namePrefix;
  
          DefaultThreadFactory() {
              SecurityManager s = System.getSecurityManager();
              //如果拿不到系统的安全manager，就拿当前线程的线程组
              group = (s != null) ? s.getThreadGroup() :
                      Thread.currentThread().getThreadGroup();
              //线程名称前缀 pool- number -thread-
              namePrefix = "pool-" +
                      //先返回number，然后再将number+1
                      poolNumber.getAndIncrement() +
                      "-thread-";
          }
  
          public Thread newThread(Runnable r) {
              //new了一个Thread，Thread的构造方法中也没什么稀奇的就是配置了一些线程信息，
              // 比如线程name，group，初始化之类的
              // ⭐️ 注意这里传入了 runnable r，所以线程启动会调用r的run 方法
              Thread t = new Thread(group, r,
                      namePrefix + threadNumber.getAndIncrement(),
                      0);
              if (t.isDaemon())
                  t.setDaemon(false);
              if (t.getPriority() != Thread.NORM_PRIORITY)
                  t.setPriority(Thread.NORM_PRIORITY);
              return t;
          }
      }
  
      /**
       * Thread factory capturing access control context and class loader.
       */
      private static class PrivilegedThreadFactory extends DefaultThreadFactory {
          final AccessControlContext acc;
          final ClassLoader ccl;
  
          PrivilegedThreadFactory() {
              super();
              // Android-removed: System.getSecurityManager always returns null.
              /*
              SecurityManager sm = System.getSecurityManager();
              if (sm != null) {
                  // Calls to getContextClassLoader from this class
                  // never trigger a security check, but we check
                  // whether our callers have this permission anyways.
                  sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
  
                  // Fail fast
                  sm.checkPermission(new RuntimePermission("setContextClassLoader"));
              }
              */
              this.acc = AccessController.getContext();
              this.ccl = Thread.currentThread().getContextClassLoader();
          }
  
          public Thread newThread(final Runnable r) {
              return super.newThread(new Runnable() {
                  public void run() {
                      AccessController.doPrivileged(new PrivilegedAction<Void>() {
                          public Void run() {
                              Thread.currentThread().setContextClassLoader(ccl);
                              r.run();
                              return null;
                          }
                      }, acc);
                  }
              });
          }
      }
  
      /**
       * A wrapper class that exposes only the ExecutorService methods
       * of an ExecutorService implementation.
       */
      private static class DelegatedExecutorService
              extends AbstractExecutorService {
          // Android-added: @ReachabilitySensitive
          // Needed for FinalizableDelegatedExecutorService below.
          @ReachabilitySensitive
          private final ExecutorService e;
  
          DelegatedExecutorService(ExecutorService executor) {
              e = executor;
          }
  
          public void execute(Runnable command) {
              e.execute(command);
          }
  
          public void shutdown() {
              e.shutdown();
          }
  
          public List<Runnable> shutdownNow() {
              return e.shutdownNow();
          }
  
          public boolean isShutdown() {
              return e.isShutdown();
          }
  
          public boolean isTerminated() {
              return e.isTerminated();
          }
  
          public boolean awaitTermination(long timeout, TimeUnit unit)
                  throws InterruptedException {
              return e.awaitTermination(timeout, unit);
          }
  
          public Future<?> submit(Runnable task) {
              return e.submit(task);
          }
  
          public <T> Future<T> submit(Callable<T> task) {
              return e.submit(task);
          }
  
          public <T> Future<T> submit(Runnable task, T result) {
              return e.submit(task, result);
          }
  
          public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
                  throws InterruptedException {
              return e.invokeAll(tasks);
          }
  
          public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                               long timeout, TimeUnit unit)
                  throws InterruptedException {
              return e.invokeAll(tasks, timeout, unit);
          }
  
          public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
                  throws InterruptedException, ExecutionException {
              return e.invokeAny(tasks);
          }
  
          public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                                 long timeout, TimeUnit unit)
                  throws InterruptedException, ExecutionException, TimeoutException {
              return e.invokeAny(tasks, timeout, unit);
          }
      }
  
      private static class FinalizableDelegatedExecutorService
              extends DelegatedExecutorService {
          FinalizableDelegatedExecutorService(ExecutorService executor) {
              super(executor);
          }
  
          protected void finalize() {
              super.shutdown();
          }
      }
  
      /**
       * A wrapper class that exposes only the ScheduledExecutorService
       * methods of a ScheduledExecutorService implementation.
       */
      private static class DelegatedScheduledExecutorService
              extends DelegatedExecutorService
              implements ScheduledExecutorService {
          private final ScheduledExecutorService e;
  
          DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
              super(executor);
              e = executor;
          }
  
          public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
              return e.schedule(command, delay, unit);
          }
  
          public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
              return e.schedule(callable, delay, unit);
          }
  
          public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
              return e.scheduleAtFixedRate(command, initialDelay, period, unit);
          }
  
          public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
              return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
          }
      }
  
      /**
       * Cannot instantiate.
       */
      private Executors() {
      }
  }
  