1203-AsyncTask详解一:线程池的基本设置

AsyncTask的内部使用线程池处理并发,要了解它是怎样使用线程池的,那要先了解线程池的基本设置

线程池的基本参数

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        // ......
    }
  • corePoolSize: 核心线程数目,即使线程池没有任务,核心线程也不会终止(除非设置了allowCoreThreadTimeOut参数),可以理解为“常驻线程”
  • maximumPoolSize: 线程池中允许的最大线程数目;一般来说,线程越多,线程调度开销越大;因此一般都有这个限制
  • keepAliveTime: 当线程池中的线程数目比核心线程多的时候,如果超过这个keepAliveTime的时间,多余的线程会被回收;这些与核心线程相对的线程通常被称为缓存线程
  • unit: keepAliveTime的时间单位
  • workQueue: 任务执行前保存任务的队列;这个队列仅保存由execute提交的Runnable任务
  • threadFactory: 用来构造线程池的工厂;一般都是使用默认的
  • handler: 当线程池由于线程数目和队列限制而导致后续任务阻塞的时候,线程池的处理方式。

线程池如何调度线程

当一个新的任务来时,线程池是如何调度线程的?

  1. 如果线程池中线程的数目少于corePoolSize,就算线程池中有其他的没事做的核心线程,线程池还是会重新创建一个核心线程;直到核心线程数目到达corePoolSize(常驻线程就位)
  2. 如果线程池中线程的数目大于或者等于corePoolSize,但是工作队列workQueue没有满,那么新的任务会放在队列workQueue中,按照FIFO的原则依次等待执行;(当有核心线程处理完任务空闲出来后,会检查这个工作队列然后取出任务去执行)
  3. 如果线程池中线程数目大于等于corePoolSize,并且工作队列workQueue满了,但是总线程数目小于maximumPoolSize,那么直接创建一个线程处理被添加的任务。
  4. 如果工作队列满了,并且线程池中线程的数目到达了最大数目maximumPoolSize,那么就会用最后一个构造参数handler处理;默认的处理方式是直接拒绝任务,然后抛出一个异常

总结起来说,当有新的任务要处理时,先看线程池中的线程数量是否大于 corePoolSize,再看缓冲队列 workQueue 是否满,最后看线程池中的线程数量是否大于 maximumPoolSize。另外,当线程池中的线程数量大于 corePoolSize 时,如果里面有线程的空闲时间超过了 keepAliveTime,就将其移除线程池,这样,可以动态地调整线程池中线程的数量。

推荐阅读更多精彩内容