Android中的线程形态
AsyncTask
底层用到了线程池。AsyncTask封装了线程池和Handler,它主要是为了方便开发者在子线程中更新UI。AsyncTask内的Handler是一个静态的Handler对象,为了能够将执行环境切换到主线程,这就要求Handler这个对象必须在主线程中创建。由于静态成员会在加载类的时候进行初始化,因此这就变相要求AsyncTask的类必须在主线程中加载,否则同一个进程中的AsyncTask都无法正常工作。
注意:从Android 3.0开始,默认情况下AsyncTask是串行执行的。但在Android 3.0之前是并行执行的。
IntentService
底层直接使用了线程,IntentService是一个服务,系统对其进行了封装使其可以更方便地执行后台任务,IntentService内部采用HandlerThread来执行任务,当任务执行完毕后IntentService会自动退出。特殊的Service,它继承了Service并且它是抽象类。IntentService可用于执行后台耗时的任务,当任务执行后它会自动停止,同时由于IntentService是服务的原因,这导致他的优先级比单纯的线程要高很多,所以IntentService比较适合执行一些高优先级的后台任务。
HandlerThread
底层直接使用了线程,HandlerThread是一中消息循环的线程,在它的内部可以使用Handler。HandlerThread继承了Thread,它是一种可以使用Handler的Thread,它的实现很简单,就在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,这样在实际的使用中就允许在HandlerThread中创建Handler。
Android中的线程池
线程池的优点:
- 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
- 能有效控制线程池中的最大并发数,避免大量的线程之间因为互相抢占系统资源而导致的阻塞现象。
- 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。
Android中的线程池的概念来源于Java中的Executor,Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor。
ThreadPoolExecutor提供一系列参数来配置线程池,通过不同的参数可以创建不同的线程池,从线程池的功能特性来说,线程池主要分为4类。
ThreadPoolExecutor执行任务时大致遵循以下规则:
- 如果线程池中的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务。
- 如果线程中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等待执行。
- 如果在步骤2中无法将任务插入到任务队列中,这往往是由于任务队列已经满了, 这个时候如果线程数量未达到线程池规定的最大值,那么会立刻启动一个非核心线程来执行任务。
- 如果步骤3的中线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。
- 线程池主要有4类:
- FixThreadPool:这是一种线程数量固定的线程池,当线程处于空闲的时候,并不会被回收,除非线程池被关闭了。
- CachedThreadPool:这是一种线程数量不定的线程池,它只有非核心线程,并且最大线程数为Integer.MAX_VALUE。
- ScheduledThreadPool:它的核心线程数量是固定的,而非核心线程数是没有限制的,并且当非核心线程闲置时会被立即回收。
- SingleThreadExecutor:这类线程池内部只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。