java 四种线程池

来源:互联网 发布:淘宝网中年女夏装 编辑:程序博客网 时间:2024/06/06 20:11

Java通过Executors提供四种线程池,各有用处,下面是列子:

package executor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;/**   * <p>线程池</p>Java通过Executors提供四种线程池,分别为:newCachedThreadPool    -- 创建一个可缓存线程池,如果线程池长度超过处理需要,    -- 可灵活回收空闲线程,若无可回收,则新建线程。newFixedThreadPool     -- 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。newScheduledThreadPool     -- 创建一个定长线程池,支持定时及周期性任务执行。newSingleThreadExecutor     -- 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,    -- 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。* @title          - ThreadPool.java * @author         - NingZhong.Zeng   * @date           - 2015年11月26日 上午11:01:32 */public class ThreadPool {    public static void main(String[] args) {         cachedThreadPool();        fixedThreadPool();        scheduledThreadPool();        singleThreadExecutor();    }    /**     * -- 创建一个可缓存线程池,如果线程池长度超过处理需要,       -- 可灵活回收空闲线程,若无可回收,则新建线程。       优点:长度伸缩性好       缺点:开销大,PV大容易吃内存     */    public static void cachedThreadPool(){        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();        for (int i = 0; i < 100; i++) {            final int index = i;            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            cachedThreadPool.execute(new Runnable() {                public void run() {                    System.out.println(index);                }            });        }    }    /**     * -- 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。     * 优点:开销小       缺点:需要等待     */    public static void fixedThreadPool() {        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);        for (int i = 0; i < 100; i++) {            final int index = i;            fixedThreadPool.execute(new Runnable() {                public void run() {                    try {                        System.out.println(index);                        Thread.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            });        }    }    /**     * -- 创建一个定长线程池,支持定时及周期性任务执行。     */    public static void scheduledThreadPool() {        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);        // 定时2s执行        scheduledThreadPool.schedule(new Runnable() {            public void run() {                System.out.println("delay 2 seconds");            }        }, 2, TimeUnit.SECONDS);        // 定时1s,循环3s执行        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {            public void run() {                System.out.println("delay 1 seconds, and excute every 3 seconds");            }        }, 1, 3, TimeUnit.SECONDS);        scheduledThreadPool.scheduleWithFixedDelay(new Runnable() {            public void run() {                System.out.println("delay 3 seconds, and excute every 1 seconds");            }        }, 3, 1, TimeUnit.SECONDS);    }    /**     * 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,     */    public static void singleThreadExecutor() {        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();        for (int i = 0; i < 100; i++) {            final int index = i;            singleThreadExecutor.execute(new Runnable() {                public void run() {                    try {                        System.out.println(index);                        Thread.sleep(2000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            });        }    }}

Executors 的源码如下:

/* * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * *//* * * * * * * 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 java.util.*;import java.util.concurrent.atomic.AtomicInteger;import java.security.AccessControlContext;import java.security.AccessController;import java.security.PrivilegedAction;import java.security.PrivilegedExceptionAction;import java.security.PrivilegedActionException;import java.security.AccessControlException;import sun.security.util.SecurityConstants;/** * 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 <tt>Callable</tt>. * </ul> * * @since 1.5 * @author Doug Lea */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     * <tt>nThreads</tt> 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}     */    public static ExecutorService newFixedThreadPool(int nThreads) {        return new ThreadPoolExecutor(nThreads, nThreads,                                      0L, TimeUnit.MILLISECONDS,                                      new LinkedBlockingQueue<Runnable>());    }    /**     * 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 <tt>nThreads</tt> 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     * <tt>newFixedThreadPool(1)</tt> the returned executor is     * guaranteed not to be reconfigurable to use additional threads.     *     * @return the newly created single-threaded Executor     */    public static ExecutorService newSingleThreadExecutor() {        return new FinalizableDelegatedExecutorService            (new ThreadPoolExecutor(1, 1,                                    0L, TimeUnit.MILLISECONDS,                                    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 <tt>newFixedThreadPool(1, threadFactory)</tt> 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 <tt>execute</tt> 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     */    public static ExecutorService newCachedThreadPool() {        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     * <tt>newScheduledThreadPool(1)</tt> 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 <tt>newScheduledThreadPool(1, threadFactory)</tt>     * 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 <tt>ExecutorService</tt> 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 <tt>ScheduledExecutorService</tt> instance     * @throws NullPointerException if executor null     */    public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {        if (executor == null)            throw new NullPointerException();        return new DelegatedScheduledExecutorService(executor);    }    /**     * 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}. If there is a {@link     * java.lang.SecurityManager}, it uses the group of {@link     * System#getSecurityManager}, else the group of the thread     * invoking this <tt>defaultThreadFactory</tt> method. Each new     * thread is created as a non-daemon thread with priority set to     * the smaller of <tt>Thread.NORM_PRIORITY</tt> 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();    }    /**     * Returns a thread factory used to create new threads that     * have the same permissions as the current thread.     * This factory creates threads with the same settings as {@link     * Executors#defaultThreadFactory}, additionally setting the     * AccessControlContext and contextClassLoader of new threads to     * be the same as the thread invoking this     * <tt>privilegedThreadFactory</tt> method.  A new     * <tt>privilegedThreadFactory</tt> can be created within an     * {@link AccessController#doPrivileged} action setting the     * current thread's access control context to create threads with     * the selected permission settings holding within that action.     *     * <p> Note that while tasks running within such threads will have     * the same access control and class loader settings as the     * current thread, they need not have the same {@link     * java.lang.ThreadLocal} or {@link     * java.lang.InheritableThreadLocal} values. If necessary,     * particular values of thread locals can be set or reset before     * any task runs in {@link ThreadPoolExecutor} subclasses using     * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is     * necessary to initialize worker threads to have the same     * InheritableThreadLocal settings as some other designated     * thread, you can create a custom ThreadFactory in which that     * thread waits for and services requests to create others that     * will inherit its values.     *     * @return a thread factory     * @throws AccessControlException if the current access control     * context does not have permission to both get and set context     * class loader.     */    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     * <tt>Callable</tt> to an otherwise resultless action.     * @param task the task to run     * @param result the result to return     * @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 <tt>null</tt>.     * @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(); }};    }    /**     * Returns a {@link Callable} object that will, when     * called, execute the given <tt>callable</tt> under the current     * access control context. This method should normally be     * invoked within an {@link AccessController#doPrivileged} action     * to create callables that will, if possible, execute under the     * selected permission settings holding within that action; or if     * not possible, throw an associated {@link     * AccessControlException}.     * @param callable the underlying task     * @return a callable object     * @throws NullPointerException if callable null     *     */    public static <T> Callable<T> privilegedCallable(Callable<T> callable) {        if (callable == null)            throw new NullPointerException();        return new PrivilegedCallable<T>(callable);    }    /**     * Returns a {@link Callable} object that will, when     * called, execute the given <tt>callable</tt> under the current     * access control context, with the current context class loader     * as the context class loader. This method should normally be     * invoked within an {@link AccessController#doPrivileged} action     * to create callables that will, if possible, execute under the     * selected permission settings holding within that action; or if     * not possible, throw an associated {@link     * AccessControlException}.     * @param callable the underlying task     *     * @return a callable object     * @throws NullPointerException if callable null     * @throws AccessControlException if the current access control     * context does not have permission to both set and get context     * class loader.     */    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     */    static final class RunnableAdapter<T> implements Callable<T> {        final Runnable task;        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     */    static final class PrivilegedCallable<T> implements Callable<T> {        private final Callable<T> task;        private 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     */    static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {        private final Callable<T> task;        private final AccessControlContext acc;        private final ClassLoader ccl;        PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {            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     */    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();            group = (s != null) ? s.getThreadGroup() :                                  Thread.currentThread().getThreadGroup();            namePrefix = "pool-" +                          poolNumber.getAndIncrement() +                         "-thread-";        }        public Thread newThread(Runnable r) {            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     */    static class PrivilegedThreadFactory extends DefaultThreadFactory {        private final AccessControlContext acc;        private final ClassLoader ccl;        PrivilegedThreadFactory() {            super();            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.     */    static class DelegatedExecutorService extends AbstractExecutorService {        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);        }    }    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.     */    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() {}}
0 0
原创粉丝点击