Android中使用Executors创建线程池的方式

先来看一下Executors类在Android系统中的源码定义:

package java.util.concurrent;

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>
 *
 * @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
     * {@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}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        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
     */
    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 {@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
     */
    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
     * {@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);
    }

    /**
     * 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();
    }

    /**
     * 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(); }};
    }

    /**
     * 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);
    }

    /**
     * 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) {
            // BEGIN Android-removed
            // 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"));
            // }
            // END Android-removed
            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();
            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.
     */
    private static class PrivilegedThreadFactory extends DefaultThreadFactory {
        final AccessControlContext acc;
        final ClassLoader ccl;

        PrivilegedThreadFactory() {
            super();
            // BEGIN Android-removed
            // 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"));
            // }
            // END Android-removed
            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 {
        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() {}
}

 Executors 类究竟是如何使用的?

1. newFixedThreadPool,创建定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化。当某个任务执行结束后会释放线程使其处于空闲状态,如果有其他任务在等待执行,可以获取这个空闲的线程资源,执行耗时任务。当线程发生错误结束时,线程池会补充一个新的线程。

看下面这个例子:创建一个工作线程数为3的线程池,然后提交4个工作任务:

package com.xw.executosmultithreaddemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testNewFixedThreadPool();
    }

    private void testNewFixedThreadPool(){
        //创建工作线程数为 3 的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        //提交 4个任务
        fixedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" A" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" A" + "任务结束.....");
            }
        });
        fixedThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" B" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" B" + "任务结束.....");
            }
        });
        fixedThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" C" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" C" + "任务结束.....");
            }
        });
        fixedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" D" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" D" + "任务结束.....");
            }
        });

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //关闭线程池后,已提交的任务仍然会执行完
        System.out.println("开始关闭线程池."+System.currentTimeMillis());
        fixedThreadPool.shutdown();
        System.out.println("关闭线程池完毕."+System.currentTimeMillis());
    }
}

上面的代码因为创建一个工作线程数为3的线程池,然后创建了标记为A、B、C、D的4个工作任务。首先创建提交的前三个工作任务A、B、C被3个子线程几乎同时处理了(每个1秒打印一个数字)。当第四秒时调用了关闭线程池的方法shutdown(),但这个线程池以及开启的任务任然还可以执行,以及的在队列中排队等待的第四个工作任务D也都可以被执行,直到所有任务结束才关闭线程池。A、B、C任务继续执行打印数字,直到pool-2-thread-2 B任务结束,空闲出一个线程被正在队列等待的任务D获取、执行打印任务。所以任务D的线程名为:pool-2-thread-2。

输出结果:

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===0

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===1

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===2

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===3

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===4
com.xw.executosmultithreaddemo I/System.out: 开始关闭线程池.1592558042796
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
com.xw.executosmultithreaddemo I/System.out: 关闭线程池完毕.1592558042797

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===5

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===6

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B任务结束.....
//上面一行,可以看出pool-2-thread-2 B 先结束任务,线程被释放,此时在队列等待的任务D 立即获得这个线程资源执行打印任务
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
//pool-2-thread-2 ---> D
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 D任务结束.....

2. newCachedThreadPool,创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制。

创建可缓存的线程池,不需要指定线程的数量,创建4个工作任务后,线程开始工作,在第五秒后新建第5个工作任务,可以看出这5个线程一起并发执行了打印任务。

package com.xw.executosmultithreaddemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testnewCachedThreadPool();
    }

    private void testnewCachedThreadPool(){
    
        //创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

        //提交 4个任务
        cachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" A" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" A" + "任务结束.....");
            }
        });
        cachedThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" B" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" B" + "任务结束.....");
            }
        });
        cachedThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" C" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" C" + "任务结束.....");
            }
        });
        cachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" D" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" D" + "任务结束.....");
            }
        });

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        cachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" E"+ "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" E" + "任务结束.....");
            }
        });


    }
}

打印结果可以看出,创建的线程数与第一次创建提交的任务数相等(4个),而5秒后再次创建提交一个任务,也是可以立即被执行的。所以线程数量随任务数可以伸缩增加。

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===0

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===1

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===2

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===3

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===4
//第五个线程开启 开始工作了
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===0

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===5

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===6

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===7

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-4 D任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B任务结束.....

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-5 E任务结束.....

3. newScheduledThreadPool,创建定长线程池,可执行周期性的任务。

注意通过newScheduledThreadPool对象调用scheduleWithFixedDelay()与execute()方法的区别:

① 使用scheduleWithFixedDelay()每次执行完任务A后,延迟3s后再次周而复始的执行任务A;

② 使用execute()方法,任务B只会被执行一次,结束后,不会再执行任务B。

package com.xw.executosmultithreaddemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testScheduledThreadPool();
    }


    private void testScheduledThreadPool(){
        
        //创建定长线程池,可执行周期性的任务。注意scheduleWithFixedDelay()与execute()方法的区别
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

        //提交 2个任务
        scheduledThreadPool.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" A" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" A" + "任务结束.....");
            }
        },0,3, TimeUnit.SECONDS);

        scheduledThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" B" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" B" + "任务结束.....");
            }
        });

    }
}

打印结果:

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
 I/System.out: Failed parserXml +java.io.FileNotFoundException: data/bbkc
 I/System.out: Failed parserXml +java.io.FileNotFoundException: data/bbkc
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
.....
//呈周期性执行线程 pool-2-thread-1 A

上面的例子我们只提交了2个任务,小于线程池里能用的线程数量3。思考一个问题,当我们提交的任务大于线程池可用的线程数量时,肯定有一个线程需要排队等候可用线程的释放,然后获取使用。那么是可周而复始的线程先获取这个刚刚释放的线程来用,还是在等待执行的任务先获得呢?

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===6

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 C任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 B任务结束.....
//所有线程都被释放了 正在排队的任务D获取了第一个线程:pool-2-thread-1 D
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===0

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===5
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D任务结束.....
//A周而复始的执行
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===6
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A===7
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-3 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-2 A===1
......

上面的注释已经回答了。是在排队的任务D先获取线程。 而scheduleWithFixedDelay(),第二个参数指的是意思下次执行该任务时,需要延迟几秒,该参数不能为0,否则程序会崩溃。

4. newSingleThreadExecutor,创建单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行。

package com.xw.executosmultithreaddemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testSingleThreadPool();
    }

    private void testSingleThreadPool(){

        //单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

        //提交 4个任务
        singleThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" A" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" A" + "任务结束.....");
            }
        });

        singleThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" B" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" B" + "任务结束.....");
            }
        });

        singleThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" C" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" C" + "任务结束.....");
            }
        });

        singleThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" D" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" D" + "任务结束.....");
            }
        });

    }
}

打印结果可以看出,即使任务出现了异常,线程池还是会自动补充一个线程继续执行下面的任务

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C任务结束.....
 I/System.out: Failed parserXml +java.io.FileNotFoundException: data/bbkcore
 I/System.out: Failed parserXml +java.io.FileNotFoundException: data/bbkcore
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 D任务结束.....
I/System.out: e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaHttp
I/System.out: [OkHttp] sendRequest>>
I/System.out: [OkHttp] sendRequest<<
I/System.out: e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaHttp
I/System.out: [OkHttp] sendRequest>>
//所有任务执行完,不会再重复执行

5. newSingleThreadScheduledExecutor,创建单线程可执行周期性任务的线程池。

scheduleWithFixedDelay 固定的延迟时间执行任务; scheduleAtFixedRate 固定的频率执行任务

package com.xw.executosmultithreaddemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testSingleScheduledThreadPool();
    }

    private void testSingleScheduledThreadPool(){
        //创建工作线程数为 3 的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
        //ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

        //创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制
        //ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

        //创建定长线程池,可执行周期性的任务
        //ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

        //单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
        //ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

        //创建单线程可执行周期性任务的线程池
        ScheduledExecutorService singleScheduledThreadPool = Executors.newSingleThreadScheduledExecutor();

        //提交 3个任务
        singleScheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {

                    System.out.println(Thread.currentThread().getName()+" A" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" A" + "任务结束.....");
            }
        },0,3,TimeUnit.SECONDS);

        singleScheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {

                    System.out.println(Thread.currentThread().getName()+" B" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" B" + "任务结束.....");
            }
        },0,3,TimeUnit.SECONDS);

        singleScheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {

                    System.out.println(Thread.currentThread().getName()+" C" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" C" + "任务结束.....");
            }
        },0,3,TimeUnit.SECONDS);
    }
}

可以看出,三个任务统一延迟3秒后,再重复执行一轮任务,周而复始,若每个任务延迟时间不一致,则延迟够时间后继续执行。

com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C任务结束.....
//停顿3秒后,重复执行一轮任务
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 B任务结束.....
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===2
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===3
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C===4
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 C任务结束.....
//停顿3秒后,重复执行一轮任务
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===0
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===1
com.xw.executosmultithreaddemo I/System.out: pool-2-thread-1 A===2
....

6. newWorkStealingPool,创建任务可窃取线程池,空闲线程可以窃取其他任务队列的任务,不保证执行顺序,适合任务耗时差异较大。

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.

创建一个线程池,该线程池维护足够的线程来支持给定的并行级别,并可以使用多个队列来减少争用。并行性级别对应于活动参与或可用参与任务处理的最大线程数。线程的实际数量可以动态地增加或减少。工作窃取池不能保证提交任务的执行顺序。

package com.xw.executosmultithreaddemo;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Build;
import android.os.Bundle;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testWorkStealingThreadPool();
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    private void testWorkStealingThreadPool(){
        
        //创建3个工作线程的 任务可窃取线程池,如果不设置并行数,默认取 CPU 总核数
        ExecutorService workStealingThreadPool = Executors.newWorkStealingPool(3);
        //提交 4个任务
        workStealingThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 2; i++) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" A" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" A" + "此任务执行0.4秒,任务结束.....");
            }
        });

        workStealingThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" B" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" B" + "此任务执行0.9秒,任务结束.....");
            }
        });

        workStealingThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 8; i++) {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" C" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+" C" + "此任务执行2.4秒,任务结束.....");
            }
        });

        workStealingThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" D" + "===" + i);
                }
                System.out.println(Thread.currentThread().getName()+"D" + "此任务执行5秒,任务结束.....");
            }
        });
    }
}

空闲线程可以窃取其他任务队列的任务,不保证执行顺序

I/System.out: ForkJoinPool-1-worker-1 A===0
I/System.out: ForkJoinPool-1-worker-2 B===0
I/System.out: ForkJoinPool-1-worker-3 C===0
I/System.out: ForkJoinPool-1-worker-1 A===1
I/System.out: ForkJoinPool-1-worker-1 A此任务执行0.4秒,任务结束.....
I/System.out: ForkJoinPool-1-worker-2 B===1
I/System.out: ForkJoinPool-1-worker-3 C===1
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-2 B===2
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-3 C===2
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-2 B此任务执行0.9秒,任务结束.....
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-3 C===3
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-1 D===0
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-3 C===4
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-3 C===5
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-3 C===6
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-1 D===1
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-3 C===7
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-3 C此任务执行2.4秒,任务结束.....
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-1 D===2
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-1 D===3
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-1 D===4
m.xw.executosmultithreaddemo I/System.out: ForkJoinPool-1-worker-1D此任务执行5秒,任务结束.....

关于第六个创建线程池的方式,没有模拟出来。但它的用法没什么问题。可以再去搜索其他的文章看看newWorkStealingPool()是什么输出效果!

关于线程池的使用基本上就是这些了!总结,共勉!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章