
Android多线程之HandlerThread详解
发布日期:2021-05-06 20:20:19
浏览次数:26
分类:原创文章
本文共 3841 字,大约阅读时间需要 12 分钟。
一 HandlerThread介绍
当系统中有多个耗时任务需要执行时,每个任务都会开启一个新线程去执行耗时任务,这样会导致系统多次创建和销毁线程,从而影响性能。为了解决这一问题,Android 提供了 HandlerThread,HandlerThread 是在线程中创建一个 Looper 循环器,让 Looper 轮询消息队列,当有耗时任务进入队列时,则不需要开启新线程,在原有的线程中执行耗时任务即可,否则线程阻塞。
二 工作原理
- HandlerThread 继承 Thread,在 Thread 开始执行时跟主线程在 ActivityThread.main() 方法内执行代码逻辑类似,初始化 Looper–Looper.prepare(),轮询消息–Looper.loop()
- 初始化 Handler 时,使用 HandlerThread 线程的 Looper 对象初始化---- new Handler(Looper) 构造方法
- 至于为什么是在子线程内执行是因为此 Handler 使用的 Looper 是子线程创建的,执行 message.target.dispatchMessage() 也在子线程内,所以最终执行的 Runnable 或者 handleMessage() 也会在子线程内。
三 实例代码
// 步骤1:创建HandlerThread实例对象 // 传入参数 = 线程名字,作用 = 标记该线程 HandlerThread mHandlerThread = new HandlerThread("handlerThread"); // 步骤2:启动线程 mHandlerThread.start(); // 步骤3:创建工作线程Handler & 复写handleMessage() // 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与 其他线程进行通信 // 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行 Handler workHandler = new Handler( handlerThread.getLooper() ) { @Override public boolean handleMessage(Message msg) { ...//消息处理 return true; } }); // 步骤4:使用工作线程Handler向工作线程的消息队列发送消息 // 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作 // a. 定义要发送的消息 Message msg = Message.obtain(); //消息的标识 msg.what = 1; // b. 通过Handler发送消息到其绑定的消息队列 workHandler.sendMessage(msg);// 步骤5:结束线程,即停止线程的消息循环 mHandlerThread.quit();
四 源码分析
4.1 实例化HandlerThread
public class HandlerThread extends Thread { int mPriority; int mTid = -1; //当前线程持有的Looper对象 Looper mLooper; private @Nullable Handler mHandler; // 方式1. 默认优先级 public HandlerThread(String name) { // 通过调用父类默认的方法创建线程 super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } // 方法2. 自定义设置优先级 public HandlerThread(String name, int priority) { super(name); mPriority = priority; } ......}
4.2 启动HandlerThread
@Override public void run() { // 1. 获得当前线程的id mTid = Process.myTid(); // 2. 创建1个Looper对象 & MessageQueue对象 Looper.prepare(); // 3. 通过持有锁机制来获得当前线程的Looper对象 synchronized (this) { mLooper = Looper.myLooper(); // 发出通知:当前线程已经创建mLooper对象成功 // 此处主要是通知getLooper()中的wait() notifyAll(); } // 4. 设置当前线程的优先级 Process.setThreadPriority(mPriority); // 5. 在线程循环前做一些准备工作 // 该方法实现体是空的,由子类决定是否实现 onLooperPrepared(); // 6. 进行消息循环,即不断从MessageQueue中取消息 & 派发消息 Looper.loop(); mTid = -1; }
run() 内所做操作和 ActivityThread.main() 方法内所操作的东西大体相类似。不同的是,利用了锁机制来保证 getLooper() 获取 looper 正确。
4.3 获取实例化Handler要用到的Looper
public Looper getLooper() { // 若线程不是存活的,则直接返回null if (!isAlive()) { return null; } // 若当前线程存活,再判断线程的成员变量mLooper是否为null // 直到线程创建完Looper对象后才能获得Looper对象,若Looper对象未创建成功,则阻塞 synchronized (this) { while (isAlive() && mLooper == null) { try { // 此处会调用wait方法去等待 wait(); } catch (InterruptedException e) { } } } // 上述步骤run()使用 持有锁机制 + notifyAll() 获得Looper对象后 // 则通知当前线程的wait()结束等待 & 跳出循环 // 最终getLooper()返回的是在run()中创建的mLooper对象 return mLooper; }
- 在获得 HandlerThread 工作线程的 Looper 对象时存在一个同步的问题:只有当线程创建成功 & 其对应的 Looper 对象也创建成功后才能获得 Looper 的值,才能将创建的 Handler 与 工作线程的 Looper 对象绑定,从而将 Handler 绑定工作线程
- 解决方案:即保证同步的解决方案 = 同步锁、wait() 和 notifyAll(),即 在 run() 中成功创建 Looper 对象后,立即调用 notifyAll()通知 getLooper() 中的 wait()结束等待 & 返回 run() 中成功创建的 Looper 对象,使得 Handler 与该 Looper 对象绑定
五 总结
- HandlerThread 本质上是一个线程类,它继承了 Thread
- HandlerThread 有自己的内部 Looper 对象,可以进行 looper 循环
- 通过获取 HandlerThread 的 looper 对象传递给 Handler 对象,可以在 handleMessage 方法中执行异步任务
- 创建 HandlerThread 后必须先调用 HandlerThread.start() 方法,Thread 会先调用 run 方法,创建 Looper 对象
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2025年04月03日 20时40分58秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
剑指Offer面试题:9.二进制中1的个数
2021-05-09
《你是在做牛做马还是在做主管》- 读书笔记
2021-05-09
重新温习软件设计之路(4)
2021-05-09
MySQL数据库与python交互
2021-05-09
python如何对字符串进行html转义与反转义?
2021-05-09
开发小白也毫无压力的hexo静态博客建站全攻略 - 躺坑后亲诉心路历程
2021-05-09
golang基础--类型与变量
2021-05-09
.NetCore外国一些高质量博客分享
2021-05-09
解决WebRTC中不同的浏览器之间适配的问题
2021-05-09
深入理解JavaScript函数
2021-05-09
【spring源码系列】之【xml解析】
2021-05-09
(在模仿中精进数据可视化07)星球研究所大坝分布可视化
2021-05-09
(数据科学学习手札02)Python与R在循环语句与条件语句上的异同
2021-05-09
(数据科学学习手札27)sklearn数据集分割方法汇总
2021-05-09
(数据科学学习手札40)tensorflow实现LSTM时间序列预测
2021-05-09
[整理] 哪些集合类是线程安全的?(Java)
2021-05-09
8 个警示和学习的 5 个阶段
2021-05-09
c# 图片带水纹波动
2021-05-09