前言
本文是介绍Android中的HandlerThread。
目录
一、HandlerThread是什么
HandlerThread 是 Android 已封装好的轻量级异步通信类。官方介绍:
A
Threadthat has aLooper. TheLoopercan then be used to createHandlers.Note that just like with a regular
Thread,Thread.start()must still be called.
一个具有 Looper 的线程。该 Looper 可以用来创建 Handler。和使用常规线程一样,Thread.start() 仍必须调用。
产生背景:我们知道,耗时任务需要在子线程中进行,而线程的创建和销毁是非常消耗系统资源的,如果当任务 A 执行完了后,如果还需要执行任务 B, 那么就还需要创建一个新的子线程进行。这样性能问题就会凸显。为此,可以子线程中创建一个轮询器 Looper,当有新任务时,Looper 就开启并处理,否则就阻塞,直到下一个耗时任务的到来。因此,HandlerThread 内部封装了 Handler 和 Looper ,可以避免多次创建和销毁线程带来的性能问题。
本质:HandlerThread 是一个线程,它继承自 Thread。内部封装了 Handler 和 Looper 来进行消息的分发、循环以及处理。通过继承Thread类和封装Handler类的使用,从而使得创建新线程和与其他线程进行通信变得更加方便易用。
作用:实现多线程,在工作线程中执行任务,如耗时任务;实现异步通信、消息传递,实现工作线程和主线程(UI线程)之间的通信,即:将工作线程的执行结果传递给主线程,从而在主线程中执行相关的UI操作。
二、使用步骤
1 | // 步骤1:创建HandlerThread实例对象 |
三、源码分析
构造方法
1 | //传入线程名,默认优先级 |
HandlerThread类继承自Thread类;- 创建
HandlerThread类对象 = 创建Thread类对象 + 设置线程优先级 = 新开1个工作线程 + 设置线程优先级。
run
启动线程,mHandlerThread.start()最终会回调 HandlerThread 的 run() 方法。
1 |
|
为当前工作线程(即步骤1创建的线程)创建1个
Looper对象 &MessageQueue对象;通过持有锁机制来获得当前线程的
Looper对象;发出通知:当前线程已经创建 mLooper 对象成功;
工作线程进行消息循环,即不断从 MessageQueue 中取消息 & 派发消息。
onLooperPrepared
重写该方法,可在 Looper 创建完成之后,开始循环消息之前可做一些准备工作。
1 | /** |
getLooper
获得当前 HandlerThread 线程中的 Looper 对象。
1 | /** |
在获得
HandlerThread工作线程的Looper对象时存在一个同步的问题:只有当线程创建成功 & 其对应的Looper对象也创建成功后才能获得Looper的值,才能将创建的Handler与 工作线程的Looper对象绑定,从而将Handler绑定工作线程。解决方案:即保证同步的解决方案 = 同步锁、
wait()和notifyAll(),即 在run()中成功创建Looper对象后,立即调用notifyAll()通知getLooper()中的wait()结束等待 & 返回run()中成功创建的Looper对象,使得Handler与该Looper对象绑定。
quit/quitSafely
在 HandlerThread 不使用的时候,需要调用退出方法quit()/quitSafely(),结束线程,即停止线程的消息循环。
1 | public boolean quit() { |
总结
- HandlerThread 本质是一个线程类,继承自 Thread;
- HandlerThread 有自己的内部 Looper 对象,可以进行 Looper 循环;
- 通过获取 HandlerThread 的 Looper 对象传递给 Handler,可以在
handlerMessage()中执行异步任务; - 优点是减少了对性能的消耗,缺点是不能同时进行多任务的处理,需要等待处理,效率较低;
- 与线程池注重并发不同,HandlerThread 是一个串行队列,HandlerThread 背后已只有一个线程;
- 在 HandlerThread 不使用的时候,需要调用退出方法
quit()/quitSafely()。
引用文章: