概述
线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时的操作。在操作系统中,线程是操作系统调度的最小单元。
- AsyncTask封装了线程池和Handler,它主要方便开发者在子线程中更新UI。
- HandlerThread是一个具有消息循环的线程,在它的内部可以使用Handler。
- IntentService是一个服务,系统对它进行了封装使其可以更方便地使用后台任务,IntentService内部使用了HandlerThread来执行任务,当任务执行完毕之后IntentService会自动退出。
AsyncTask的工作原理
AsyncTask是一种轻量级的异步任务类,他可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程上更新UI。从实现上来说,AsyncTask封装了Thread和Handler。但不适合特别耗时的任务,特别耗时建议用线程池。
AsyncTask中有两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),其中线程池SerialExecutor用于任务的排队,而线程池THREAD_POOL_EXECUTOR用于真正地执行任务,InternalHandler用于将执行环境从线程池切换到主线程。
首先系统先将AsyncTask的Params参数封装为FutureTask对象,FutureTask是一个并发类,在这里它充当了Runnable的作用。接着这个FutureTask会交给SerialExecutor的execute方法去处理,SerialExecutor的execute方法首先会把FutureTask对象插入到任务队列mTasks中,如果这个时候没有正在活动的AsyncTask任务,那么就会调用SerialExecutor的scheduleNext方法来执行下一个AsyncTask任务。当一个任务执行完毕后会继续执行其他任务,可见默认情况下,AsyncTask是串行执行的。
在AsyncTask的构造方法中有如下代码,由于FutureTask的run方法会调用mWorker的call方法,因此mWorker的call方法最终会在线程池中执行:
在mWorker的call方法中,会执行AsyncTask的doInBackground方法,接着讲返回值传递给postResult方法,代码如下:
上述代码中getHandler会返回sHandler,通过它发送一个消息。sHandler的定义代码如下:
sHandler是一个静态的Handler对象,为了能够将执行环境切换到主线程,这就要求sHandler在主线程中创建,由于静态成员会在加载类的时候进行初始化,因此这就变相要求AsyncTask的类必须在主线程中加载,否则统一进程中的AsyncTask将无法正常运行。AsyncTask收到MESSAGE_POST_RESULT这个消息后会调用finish方法,代码如下:
AsyncTask的执行开始于execute方法,execute方法又会调用executeOnExecutor方法,代码如下:
AsyncTask的onPreExecutor方法最先执行,然后线程池开始执行。sDefaultExecutor实际上是一个串行的线程池,一个进程中所有的AsyncTask全部在这个串行的线程池中排队执行。排队线程池的源码如下:
对源码的分析就到这了,总体流程前面已经总结过了。。。
HandlerThread工作原理
HandlerThread继承了Thread,它是一种可以使用Handler的Thread,它的实现也是很简单,就是在run‘方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,这样在实际的使用中就允许HandlerThread中创建Handler了,HandlerThread的run方法如下所示:
可以通过它的quit或者quitSafely方法来终止线程的执行:
HandlerThread在内部创建了消息队列,外界需要通过Handler的消息方式类通知HandlerThread执行一个具体的任务,HandlerThread一个具体的使用场景就是IntentService。
IntentService的工作原理
IntentService继承了Service并且是一个抽象类,用于执行后台耗时的任务,执行完毕后自动停止。IntentService封装了HandlerThread和Handler,看一下它的onCreate方法:
创建一个HandlerThread,然后使用它的Looper来构造一个Handler对象的mServiceHandler,这样通过mServiceHandler发送的消息最终都会在HandlerThread中执行。
每次启动IntentService,它的onStartCommand方法就会被调用一次,IntentService在onStartCommand中处理每个后台任务的Intent,看一下该方法:
直接调用了onStart方法
仅仅是通过mServiceHandler发送了一条消息,这个消息会在HandlerThread中被处理
mServiceHandler收到消息后,会将Intent对象传递给复写的onHandleIntent方法去处理。同时会通过stopSelf方法来尝试停止服务,在尝试停止服务之前会判断最近启动服务的次数是否和startId相等,如果相等就立刻停止服务,不等不停止。
Android中的线程池
线程池的好处:
- 重用线程池中的线程,避免因为线程的创建和销毁所带类的性能开销
- 能有效控制线程池中的最大并发数,避免大量的线程之间互相抢占系统资源而导致的阻塞现象
- 能够对线程进行简单的管理,并提供 定时执行以及制定间隔循环执行等工功能
ThreadPoolExecutor
ThreadPoolExecutor是线程池的真正实现,它的构造方法提供了一系列参数来配置线程池,如下所示:
线程池的分类
线程池的分类很多,常用的有四种:
FixedThreadPool
线程数量固定的线程池,只有核心线程并且不会被回收,没有超时机制:
CachedThreadPool
线程数量不定,只有非核心线程,最大线程数任意大。超时时间为60秒,适合执行大量的耗时较少的任务:
ScheduleThreadPool
核心线程数固定,非核心线程数没有限制,并且非核心线程闲置时立即回收,主要用于执行定时任务和具有固定周期的重复任务
SingleThreadExecutor
只有一个核心线程,所有任务按顺序执行,线程同步: