一、为什么要使用线程池
在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、特点:这种线程池只有一个核心线程,可以把所有的任务都统一到一个线程中按顺序执行,使这些任务之间不需要考虑线程同步问题