Android中的线程池

一、为什么要使用线程池

     在Android开发中,所有的耗时任务都要放到子线程中去做,如果是自己去手动创建线程,那么就会出现线程数量过多、线程的频繁创建和销毁、线程难以管理等问题,使用线程池的优点可以总结为以下三点:

  • 可以重用线程池中的线程,避免线程的创建和销毁引起的性能开销。
  • 可以有效控制线程池的最大并发数,避免大量的线程之间抢占系统资源而造成阻塞的现象。
  • 可以对线程进行管理,并能执行定时和间隔循环任务(比如心跳)。

二、线程池的种类

     Android中的线程池来源于java中的接口Executor,ThreadPoolExecutor是对Executor的真正实现。可以通过对ThreadPoolExecutor进行不同的参数配置来创建不同的线程池,Android中的线程池有4类,分别是FixedThreadPool、CachedThreadPool、ScheduledThreadPool、SingleThreadExecutor。由于ThreadPoolExecutor是线程池的核心,那么就先介绍下这个类,然后在介绍4种内置的线程池:

  • ThreadPoolExecutor
    1、这个类是线程池中的一个核心类,其他的线程池都是通过配置它的构造方法里的参数而得到的。下面对它的构造方法里的一些常见参数进行说明:

       public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 threadFactory, defaultHandler);
        }
    
        corePoolSize  
        线程池的核心线程数,默认情况下,核心线程无论是否是空闲状态都是会一直存活的。如果将ThreadPoolExecutor的属性alilowCoreThreadTimeOut设置为true的话,
        那么核心线程就会有一个闲置超时策略,超时时间有keepAliveTime指定,如果超过这个时间,核心线程就会被回收掉。
    
        maximumPoolSize  
        线程池的最大线程数,当活跃的线程数达到这个值后,新任务就会处于等待状态(等待有空闲线程)。
    
        keepAlieTime  
        指定超时时长,线程闲置时间超过这个值就会被回收掉。默认情况下,只作用于非核心线程,但是如果将ThreadPoolExecutor的属性
        alilowCoreThreadTimeOut设置为true,也会作用于核心线程。
    
        unit
        指定keepAliveTime的时间单位,常用的有
        TimeUnit.MILLISECONDS(毫秒)
        TimeUnit.SECONDS(秒)
        TimeUnit.MINUTES(分钟)
    
        workQueue
        线程池中的任务队列,通过线程池的execute方法提交的Runnable对象会存在里面。
    
        threadFactory
        线程工厂,线程池中的线程是通过该类进行创建提供的。

    2、ThreadPoolExecutor的执行流程:

    • 如果线程池中的线程数量没有达到核心线程的数量,会直接启动一个核心线程执行任务。
    • 如果线程池的线程数量达到或者超过了核心线程数量,任务会插入到任务队列中排队等待。
    • 在第2步中,如果任务队列已满无法插入任务时,如果此时线程数量没有达到最大线程数,那么就会启动一个非核心线程来执行该任务。
    • 在第3步中,如果当前线程池中的线程数量已经达到了最大线程数,那么就拒绝执行此任务,并通知调用者。
  • FixedThreadPool
    1、创建方式:通过Executors的newFixedThreadPool方法创建。

    2、特点:这种线程池的线程数量是固定的,里面的线程都是核心线程并且这些核心线程没有超时机制,所以无论线程是否是处于空闲状态都不会被回收(除非线程池关闭了)。
       这种线程池的任务队列是没有大小限制的,如果所有的线程都处于活跃状态时,那么新任务就会添加到任务队列中进行排队等待,当有线程空闲出来时会去任务队列中取任务执行。如果任务队列中没有任务了,就保持空闲状态,直到有新任务的到来。

  • CachedThreadPool
    1、创建方式:通过Executors的newCachedThreadPool方法创建。

    2、特点:这种线程池没有固定的线程数量,也没有核心线程,都是非核心线程,最大线程数为Integer.MAX_VALUE。当有新任务的时候,如果当前有空闲线程就用空闲线程去执行任务,如没有就会创建一个新的线程去执行任务,这种机制导致这种线程池的任务队列是个空队列(有新任务时,不管是否有空闲线程,都会立刻执行,就不会在插入到队列中了)。
       这种线程池里的线程都是有超时机制的,如果超过60秒,闲置的线程就会被回收,当线程池中没有任务时,所有的线程都会因为空闲超时被回收掉,这个时候它是不占用任何系统资源的,所以这类线程池适合执行任务量多,耗时少的任务。

  • ScheduledThreadPool
    1、创建方式:通过Executors的newScheduledThreadPool方法创建。

    2、特点:这种线程池有数量固定的核心线程,而非核心线程数量没有限制,并且非核心线程闲置时会被立即回收(非核心线程有超时机制,超时时间是0)。
       这种线程池主要用于执行定时任务(schedule方法)和有固定时间间隔的循环任务(scheduleAtFixedRate方法)。

  • SingleThreadExecutor
    1、创建方式:通过Executors的newSingleThreadExecutor方法创建。

    2、特点:这种线程池只有一个核心线程,可以把所有的任务都统一到一个线程中按顺序执行,使这些任务之间不需要考虑线程同步问题

猜你喜欢

转载自blog.csdn.net/huideveloper/article/details/80464831