编程进阶网编程进阶网
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 1.1App启动流程梳理
  • 1.2ActivityThread分析
  • 1.3Context设计思想
  • 2.1Activity基础介绍
  • 2.2Activity启动流程
  • 2.3Activity布局创建
  • 2.4Activity布局绘制
  • 2.5Service基础介绍
  • 2.6Service启动流程
  • 2.7Receiver广播基础
  • 2.8Receiver深入原理
  • 2.9ContentProvider分析
  • 2.10Fragment实践
  • 2.11Intent深入思考
  • 3.1Paint和Canvas
  • 3.2View的绘制基础
  • 3.3onMeasure流程设计
  • 3.4onLayout流程设计
  • 3.5onDraw流程设计
  • 3.6View工作原理
  • 3.7View刷新设计流程
  • 3.8自定义View控件
  • 3.9自定义ViewGroup控件
  • 4.1Handler基础使用
  • 4.2消息机制流程分析
  • 4.3Handler深度解析
  • 4.4Message深度理解
  • 4.5MessageQueue解析
  • 4.6Looper深度解析
  • 4.7理解Handler同步屏障
  • 4.8ThreadLocal分析
  • 4.9ThreadLocal场景
  • 5.1View事件设计思考
  • 5.2View滑动冲突处理
  • 5.3View事件源码分析
  • 5.4View事件总结案例
  • 6.1DecorView设计思想
  • 6.2视图的载体View
  • 6.3视图管理者Window
  • 6.4窗口管理服务WMS
  • 6.5布局解析者Inflater
  • 7.1AsyncTask深入介绍
  • 7.2HandlerThread设计
  • 7.3IntentService设计
  • 8.1IPC通信方式介绍
  • 8.2AIDL进程间通信
  • 8.7Binder通信机制设计
  • /zh/android/basic/9.1注解设计思想和原理.html
  • 9.2APT技术设计详解
  • 9.3APT多种案例实践

7.2HandlerThread设计

目录介绍

  • 01.HandlerThread介绍
    • 1.1 HandlerThread定义
    • 1.2 HandlerThread简单使用
    • 1.3 HandlerThread几个特性
  • 02.HandlerThread源码分析
    • 2.1 HandlerThread构造方法
    • 2.2 HandlerThread调用start方法
    • 2.3 创建对象接受消息

好消息

  • 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计N篇[近100万字,陆续搬到网上],转载请注明出处,谢谢!
  • 链接地址:https://github.com/yangchong211/YCBlogs
  • 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!

01.HandlerThread介绍

1.1 HandlerThread定义

  • HandlerThread是个什么东西,是一个handler还是thread,还是别猜了,直接看一下类的定义吧,英文看不懂,可以找翻译?
    • 这个类的作用是创建一个包含looper的线程。
    • 那么在什么时候需要用到它呢?加入在应用程序当中为了实现同时完成多个任务,所以会在应用程序当中创建多个线程。为了让多个线程之间能够方便的通信,会使用Handler实现线程间的通信。这个时候我们手动实现的多线程+Handler的简化版就是我们HandlerThrea所要做的事了。
    Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

1.2 HandlerThread简单使用

  • 看一下HandlerThread的基本用法:
    HandlerThread mHandlerThread = new HandlerThread("myHandlerThreand");
    mHandlerThread.start();
    
    // 创建的Handler将会在mHandlerThread线程中执行
    final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            Log.i("tag", "接收到消息:" + msg.obj.toString());
        }
    };
    
    title = (TextView) findViewById(R.id.title);
    title.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
    
            Message msg = new Message();
            msg.obj = "11111";
            mHandler.sendMessage(msg);
    
            msg = new Message();
            msg.obj = "2222";
            mHandler.sendMessage(msg);
        }
    });

1.3 HandlerThread几个特性

  • HandlerThread 继承于 Thread,本身就是一个线程类。在内部维护了自己的 Looper 对象,所以可以进行 looper 循环。
  • 创建 HandlerThread 后需要先调用 HandlerThread.start() 方法再向其下发任务,通过 run() 方法来创建 Looper 对象
  • 通过传递 HandlerThread 的 Looper 对象给 Handler 对象,从而可以通过 Handler 来向 HandlerThread 下发耗时任务。博客

02.HandlerThread源码分析

2.1 HandlerThread构造方法

  • 首先定义了一个HandlerThread对象,是直接通过new的方式产生的,查看其构造方法:
    • 可以知道HandlerThread继承于Thread,所以说HandlerThread本质上是一个线程,其构造方法主要是做一些初始化的操作。
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

2.2 HandlerThread调用start方法

  • 调用了mHandlerThread.start()方法
    • 知道了HandlerThread类其实就是一个Thread,一个线程,所以其start方法内部调用的肯定是Thread的run方法,查看一下其run方法的具体实现:
    • 发现其内部调用了Looper.prepate()方法和Loop.loop()方法,关于异步消息机制可以看我这篇博客:https://github.com/yangchong211/YCBlogs
    • 通过run方法,我们可以知道在我们创建的HandlerThread线程中我们创建了该线程的Looper与MessageQueue
    • 需要注意的是其在调用Looper.loop()方法之前调用了一个空的实现方法:onLooperPrepared(),我们可以实现自己的onLooperPrepared()方法,做一些Looper的初始化操作
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

2.3 创建对象接受消息

  • 代码如下所示:
    • Handler的构造方法中传入了HandlerThread的Looper对象,所以Handler对象就相当于含有了HandlerThread线程中Looper对象的引用。
    • 然后调用handler的sendMessage方法发送消息,在Handler的handleMessge方法中就可以接收到消息了。博客
    // 创建的Handler将会在mHandlerThread线程中执行
    final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            Log.i("tag", "接收到消息:" + msg.obj.toString());
        }
    };
  • 需要注意的是在不需要这个looper线程的时候需要手动停止掉;
    protected void onDestroy() {
        super.onDestroy();
        mHandlerThread.quit();
    }
  • 相对来说HandlerThread还是比较简单的,这里总结一下:
    • HandlerThread本质上是一个Thread对象,只不过其内部帮我们创建了该线程的Looper和MessageQueue;
    • 通过HandlerThread我们不但可以实现UI线程与子线程的通信同样也可以实现子线程与子线程之间的通信;
    • HandlerThread在不需要使用的时候需要手动的回收掉;

03.HandlerThread完整源码

  • 最后看一下HandlerThread 的完整源码注释
    public class HandlerThread extends Thread {
    
        //线程优先级
        int mPriority;
    
        //线程ID
        int mTid = -1;
    
        //当前线程持有的Looper对象
        Looper mLooper;
    
        //包含当前 Looper 对象的 Handler
        private @Nullable Handler mHandler;
    
        public HandlerThread(String name) {
            super(name);
            //使用默认的线程优先级
            mPriority = Process.THREAD_PRIORITY_DEFAULT;
        }
    
        public HandlerThread(String name, int priority) {
            super(name);
            //使用自定义的线程优先级
            mPriority = priority;
        }
        
        //在 Looper 循环启动前调用
        //此处是空实现,留待子类重写
        protected void onLooperPrepared() {
        }
    
        @Override
        public void run() {
            mTid = Process.myTid();
            //触发当前线程创建 Looper 对象
            Looper.prepare();
            synchronized (this) {
                //获取 Looper 对象
                mLooper = Looper.myLooper();
                //唤醒在等待的线程
                //唤醒 getLooer() 中可能还处于等待状态的线程
                notifyAll();
            }
            //设置线程优先级
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            //开启消息循环
            Looper.loop();
            mTid = -1;
        }
        
        //获取与当前线程关联的 Looper 对象
        //因为 getLooper() 方法可能先于 run() 被调用,此时就需要先等待 Looper 对象被创建
        public Looper getLooper() {
            //如果当前线程未在运行,则返回 null 
            if (!isAlive()) {
                return null;
            }
            synchronized (this) {
                //如果当前线程已处理运行状态(已调用 start() 方法)且 Looper 对象还未创建
                //则调用 wait() 方法释放锁,等待 Looper 对象创建
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    
        /**
         * @return a shared {@link Handler} associated with this thread
         * @hide
         */
        @NonNull
        public Handler getThreadHandler() {
            if (mHandler == null) {
                mHandler = new Handler(getLooper());
            }
            return mHandler;
        }
    
        //清空消息队列中所有的消息
        public boolean quit() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quit();
                return true;
            }
            return false;
        }
    
        //清空消息队列中所有非延时消息
        public boolean quitSafely() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quitSafely();
                return true;
            }
            return false;
        }
    
        /**
         * Returns the identifier of this thread. See Process.myTid().
         */
        public int getThreadId() {
            return mTid;
        }
    }

其他介绍

01.关于博客汇总链接

  • 1.技术博客汇总
  • 2.开源项目汇总
  • 3.生活博客汇总
  • 4.喜马拉雅音频汇总
  • 5.其他汇总

02.关于我的博客

  • github:https://github.com/yangchong211
  • 知乎:https://www.zhihu.com/people/yczbj/activities
  • 简书:http://www.jianshu.com/u/b7b2c6ed9284
  • csdn:http://my.csdn.net/m0_37700275
  • 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
  • 开源中国:https://my.oschina.net/zbj1618/blog
  • 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
  • 邮箱:yangchong211@163.com
  • 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
  • segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
  • 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
贡献者: yangchong211
上一篇
7.1AsyncTask深入介绍
下一篇
7.3IntentService设计