Android线程篇(三):深入理解Java线程池(一)

上篇文章我们讲解了Java的四种线程池,我们知道如何去使用四种线程池,以及在合适的情况下使用合适的线程池,常言道,不懂原理的厨师不是好的程序员,所以本篇文章,就带大家一起去探寻Java线程池的秘密。

1.我们来先看看四种线程池的源码

  • newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue(),
                                      threadFactory);
    }

返回了ThreadPoolExecutor对象

  • newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
    }

返回了ThreadPoolExecutor对象

  • newCachedThreadPool
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue(),
                                      threadFactory);
    }

返回了ThreadPoolExecutor对象

  • newScheduledThreadPool
 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

返回了ScheduledThreadPoolExecutor对象,那我们再来看看ScheduledThreadPoolExecutor的源码

public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {

ScheduledThreadPoolExecutor又继承了ThreadPoolExecutor对象
so,没有意外,没有惊喜,还是返回了ThreadPoolExecutor对象

既然每个线程池都返回了ThreadPoolExecutor,貌似好神奇啊,那我们就来看看这是个什么玩意儿,看看到底有多神奇,到底有没有意外,到底有没有惊喜,哈哈……
通过观察ThreadPoolExecutor源码,我们发现:

  • ThreadPoolExecutor 继承自AbstractExecutorService
    public class ThreadPoolExecutor extends AbstractExecutorService {
  • ThreadPoolExecutor提供了四种构造方法
 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

仔细观察这个四个构造器,我们发现,前三个构造器都是调用第四个构造器来进行初始化的,所以我们要着重研究最后一个构造器,下面解释下一下构造器中各个参数的含义:

  • corePoolSize:核心线程池大小,创建了线程池后,默认情况下,线程池中没有任何线程(注意:是默认情况哦,证明还是其他情况哦),而是等待有任务到来才创建线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
  • maximumPoolSize:线程池最大线程数,它表示在线程池中最多能创建多少个线程;
  • keepAliveTime:表示线程池中的线程没有任务执行时最多保持多久时间会终止。默认,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;
  • unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:
        TimeUnit.DAYS //天
        TimeUnit.HOURS //小时
        TimeUnit.MINUTES //分钟
        TimeUnit.SECONDS //秒
        TimeUnit.MILLISECONDS //毫秒
        TimeUnit.MICROSECONDS //微秒
        TimeUnit.NANOSECONDS  //纳秒

-workQueue:一个阻塞队列,用来存储等待执行的任务,线程池的排队策略与BlockingQueue有关。
我们回到上面四种线程池源码看看,发现:
newFixedThreadPool使用了LinkedBlockingQueue
newSingleThreadExecutor使用了LinkedBlockingQueue
newCachedThreadPool使用了SynchronousQueue

  • threadFactory:这个很好理解,字面意思就可以理解,主要用来创建线程;
  • handlerRejectedExecutionHandler拒绝执行处理程序,当拒绝处理任务时的策略,有以下四种取值:
    1.ThreadPoolExecutor.AbortPolicy():
 private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

AbortPolicy()源码:

    /**
     * A handler for rejected tasks that throws a
     * {@code RejectedExecutionException}.
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

阅读源码,得出结论:AbortPolicy()会丢弃当前任务并抛出RejectedExecutionException异常
2.ThreadPoolExecutor.DiscardPolicy()
DiscardPolicy()源码:

    /**
     * A handler for rejected tasks that silently discards the
     * rejected task.
     */
 public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

阅读源码,得出结论:DiscardPolicy()会丢弃当前任务但不抛出异常
3.ThreadPoolExecutor.DiscardOldestPolicy()
DiscardOldestPolicy()源码:

/**
     * A handler for rejected tasks that discards the oldest unhandled
     * request and then retries {@code execute}, unless the executor
     * is shut down, in which case the task is discarded.
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
}

再来看看e.getQueue().poll()是干什么的,来上源码:

/**
     * Retrieves and removes the head of this queue,
     * or returns {@code null} if this queue is empty.
     *
     * @return the head of this queue, or {@code null} if this queue is empty
     */
    E poll();

Retrieves and removes the head of this queue, or returns {@code null} if this queue is empty:如果此队列为空,则检索并删除此队列的头部,或返回{@ code null}

阅读源码,得出结论:DiscardOldestPolicy()会丢弃队列最前面的任务,然后重新尝试执行新任务。简单来说就是:抛弃旧任务,执行新任务
4.ThreadPoolExecutor.CallerRunsPolicy()

/**
     * A handler for rejected tasks that runs the rejected task
     * directly in the calling thread of the {@code execute} method,
     * unless the executor has been shut down, in which case the task
     * is discarded.
     */
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

阅读源码,得出结论:CallerRunsPolicy ()会重新添加当前的任务,他会自动重复调用execute()方法
文章开头不久我们发现,ThreadPoolExecutor 继承自AbstractExecutorService,那么我们下篇文章就来扒光它的衣服,看看它真实的样子……

你可能感兴趣的:(Android线程篇(三):深入理解Java线程池(一))