美文网首页Android开发Android 开发相关文章收集Android知识
Android线程篇(三):深入理解Java线程池(一)

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

作者: 小五666 | 来源:发表于2017-12-10 14:12 被阅读0次

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

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

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

    返回了ThreadPoolExecutor对象

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

    返回了ThreadPoolExecutor对象

    • newCachedThreadPool
    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>(),
                                          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<Runnable> workQueue) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), defaultHandler);
        }
    
    
     public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 threadFactory, defaultHandler);
        }
    
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  RejectedExecutionHandler handler) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), handler);
        }
    
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> 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线程池(一)

        本文链接:https://www.haomeiwen.com/subject/kvrpixtx.html