当前位置: 首页 > news >正文

Android Handler机制(二) Handler 实现原理

一. 前言

        接上一篇文章为什么设计Handler , 我们来继续讲解一下Handler的实现原理, 俗话说一个好汉三个帮, 接下来一步一步引入各个主角,并说明它们在Handler机制中扮演的角色和作用.

二. Handler实现原理

        首先我们先确定一个结论:  使用 Handler 是希望它被实例化在哪个线程,哪个线程就是消息的接收端,在其他线程内发送消息时,调用的还是这个 Handler对象的 sendMessage(xx).

结论支撑可以看之前的博客:  HandlerThread源码理解

图一:

图二: 

 

我们再来看一张关于多线程之间的通信图

 这个图也可以得出如下结论:Handler 接收消息端是线程独立的,不管 handler的引用在哪个线程发送消息都会传回自己被实例化的那个线程中.

但显而易见的是 Handler 不可能是线程独立的,因为它的引用会在别的线程作为 消息的发送端,也就是说它本身就是多线程共享的引用,不可能独立存在于某个线程内.

所以!Handler 需要一个独立存在于线程内部且私有使用的类帮助它接收消息! 这个类就是 Looper!

三. Looper -线程独立

        通过上节我们已经知道设计Looper就是为了辅助Handler接收消息且仅独立于线程内部。那如何才能实现线程独立的呢?

        Java 早就考虑到了这一点,早在 JDK 1.2 的版本中就提供 ThreadLocal 这么一个工具类来帮助开发者实现线程独立。

        那为什么要理解ThreadLocal呢? 因为Looper源码中有这一段代码

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();private static void prepare(boolean quitAllowed) {if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocal.set(new Looper(quitAllowed));}

这样子就实现了Looper线程独立. 

理解ThreadLocal 原理需要先掌握一下 java强软弱虚引用基本概念, 参考笔者之前写的博客:

java 强软弱虚引用和ThreadLocal工作原理

到这里就可以支撑这个结论:有了ThreadLocal 之后我们只需要把 Looper 存进去就能实现线程独立了.

到这里再梳理一下流程:

 1. Handler 引用可以多线程间共享。

2. 当 Handler 对象在其他线程发送消息时,通过 Handler 的引用找到它所在线程的 Looper 接收消息。

3. Looper 负责接收消息再分发给 Handler 的接收消息方法

这里我们再提一个问题: 如果多个线程同时使用一个 Handler 发消息,Looper 该怎么办?给接收消息的方法上锁吗?

回答: 显然不能这样做

解决方法呢? 

google工程师就设计出MessageQueue来解决这个问题.

 

四. MessageQueue - 多线程同时发消息

        为了防止多个线程同时发送消息 Looper 一下着忙不过来,于是设计一个 MessageQueue 类以队列的方式保存着待发送的消息,这样 Looper 就可以一个个 的有序的从 MessageQueue 中取出消息处理了。 既然 MessageQueue 是为 Looper 服务的,而 Looper 又是线程独立的,所以 MessageQueue 也是线程独立的. 

        MessageQueue 看名字应该是个队列结构,队列的特点是什么?先进先出,一般在队尾增加数据,在队首进行取数据或者删除数据。那Handler中的消息似乎也满足这样的特点,先发的消息肯定就会先被处理。但是,Handler中还有比较特殊的情况,比如延时消息。
延时消息的存在就让这个队列有些特殊性了,并不能完全保证先进先出,而是需要根据时间来判断,所以Android中采用了链表的形式来实现这个队列,也方便了数据的插入.

数据结构中队列和链表的基本概念理解,请参考笔者博客:

五. 总结

现在我们已经知道为了完成异步消息功能需要有 Handler 家族的四位成员共同合作:

Handler: 负责发送消息,为开发者提供发送消息与接收消息的方法。

Message: 消息载体,负责保存消息具体的数据。

MessageQueue:消息队列,以队列形式保存着所有待处理的消息,  原理实现采用的是链表.

Looper:消息接受端,负责不断从 MessageQueue 中取出消息分发给 Handler 接受消息端

这四位成员哪个都不是平白无故出现的。因为要规范化消息传递格式而定义了 Message;

为了实现消息接收端只存在线程内部私有化使用而定义了 Looper;

为 了解决多线程同时发送数据 Looper 分发消息处理时会产生的问题而设计 MessageQueue 队列化消息。

到这里你应该知道了 Handler 家族四位成员各自负责的是什么工作,以及他们自身的特点特殊性,比如 Handler 是线程间共享的而 Looper 是线程独立的, MessageQueue 跟 Looper 又是一对一的。

工作图:

 

相关文章:

Android Handler机制(二) Handler 实现原理

一. 前言 接上一篇文章为什么设计Handler , 我们来继续讲解一下Handler的实现原理, 俗话说一个好汉三个帮, 接下来一步一步引入各个主角,并说明它们在Handler机制中扮演的角色和作用. 二. Handler实现原理 首先我们先确定一个结论: 使用 Handler 是希望它被实例化在哪个线程&a…...

Elasticsearch教程(19) 详解mapping之keyword

Elasticsearch已升级&#xff0c;新版Elasticsearch keyword博客参考下面这篇【Elasticsearch教程8】Mapping字段类型之keyword_elasticsearch的keyword_亚瑟弹琴的博客-CSDN博客 1 前言 本文基于ES7.6&#xff0c;如果是之前版本&#xff0c;是有区别的。 ES支持的字段类型很…...

LeetCode算法复杂度分析(时间复杂度空间复杂度)

文章目录前言时间复杂度1.概述2.大O记法3.常见类型空间复杂度1.概述2.常见类型典型算法的复杂度分析1.递归算法2.哈希表前言 我们知道&#xff0c;研究算法的最终目的就是如何花更少的时间&#xff0c;如何占用更少的内存去完成相同的需求。 时间复杂度 1.概述 我们要计算算…...

Android OpenCV(七十三):吊打高斯模糊的StackBlur Android 实践

前言 OpenCV 4.7.0 2022年12月28日Release,ChangeLog中提到 Stackblur algorithm implementation. Stackblur是一种高斯模糊的快速近似,由Mario Klingemann发明。其计算耗时不会随着kernel size的增大而增加,专为大kernel size的模糊滤波场景量身定制。 使用建议:当kerne…...

4.排序算法之一:冒泡排序

排序算法稳定性假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#xff0c;这些记录的相对次序保持不变&#xff0c;即在原序列中&#xff0c;r[i]r[j]&#xff0c;且r[i]在r[j]之前&#xff0c;而在排序后的序列中&#xff0c;r[…...

python自学之《21天学通Python》(16)——第19章 用Pillow库处理图片

Pillow是Python2.X时代比较流行的Python ImagingLibrary&#xff08;简称Pillow&#xff09;图像处理库的分支&#xff0c;并修复了一些bug。Pillow提供了对Python3的支持&#xff0c;为Python3解释器提供了图像处理的功能。和Pillow库一样提供了广泛的文件格式支持、高效的内部…...

发布依赖到maven仓库

maven中央仓库是一个开放的仓库&#xff0c;所以我们也可以把自己开发的jar推送到远程仓库&#xff0c;这样可以直接引入pom依赖使用我们的库。 准备工作 ● 需要一个github账号&#xff08;程序员必备&#xff09; ● 网络代理&#xff08;涉及到的网站通常没版本在国内直接访…...

Laravel-admin之自定义操作日志

laravel-admin是封装性极好的框架&#xff0c;自带的就有操作日志的记录&#xff0c;但是对于非开发人员可能看不懂这个日志&#xff0c;所以就想着给修改一下&#xff0c;以谁修改了什么&#xff0c;谁删除了什么&#xff0c;谁审核了什么&#xff0c;谁添加了什么类似&#x…...

用Python做了一个法律查询小工具,非常好用

用Python做了一个法律查询小工具&#xff0c;非常好用效果展示准备工作不会的话可以点我直达代码和视频讲解&#xff0c;我都准备好了主要代码哈喽兄弟&#xff0c;今天给大家分享一个Python tkinter制作法律查询小工具。 光爬虫大家也只能自己用用&#xff0c;就算打包了exe&…...

工作篇:触摸屏原理介绍

一、触摸屏概述 触摸屏作为一种新的输入设备&#xff0c;它是目前最简单、方便、自然的一种人机交互方式。 当接触了屏幕上的图形按钮时&#xff0c;屏幕上的触觉反馈系统可根据预先编程的程式驱动各种连结装置&#xff0c;可用以取代机械式的按钮面板&#xff0c;并借由液晶…...

Ep_操作系统面试题-操作系统的分类

答案 单体系统 整个操作系统是以程序集合来编写的&#xff0c;链接在一块形成一个二进制可执行程序&#xff0c;这种系统称为单体系统。 分层系统 每一层都使用下面的层来执行其功能。 微内核 微内核架构的内核只保留最基本的能力&#xff0c;把一些应用放到了用户空间 客户-…...

iframe或document监听滚动事件不起作用

有时候我们会遇到监听iframe或document的滚动事件不起作用的情况&#xff0c;在排除代码写错的情况下&#xff0c;我们应该考虑此时的document是否可以滑动。 1、为什么document不能监听滑动? 就很奇怪&#xff0c;明明页面时有滚动条的&#xff0c;为什么说document不可滑动…...

基频估计算法简介

基频估计算法 F0 estimate methods 估计F0的方法可以分为三类:基于时域、基于频域、或混合方法。本文详细介绍了这些方法。 所有的算法都包含如下三个主要步骤&#xff1a; 1.预处理&#xff1a;滤波&#xff0c;加窗分帧等 2.搜寻&#xff1a;可能的基频值F0&#xff08;候选…...

linux修改DNS 系统版本Kylin V10桌面版

配置DNS在银河麒麟桌面操作系统V10 SP1 中修改DNS信息&#xff0c;直接修改/etc/resolv.conf文件中的DNS信息&#xff0c;不能生效。应该参考如下步骤&#xff1a;一、首先修改 /etc/systemd/resolved.conf文件&#xff0c;在其中添加DNS信息在终端中执行以下命令&#xff1a;s…...

如何使用 AWS Lambda 运行 selenium

借助 AWS Lambda 运行 selenium 来爬取网络数据。 简介 与手动从网站收集数据相比&#xff0c;爬虫可以为我们节省很多时间&#xff0c;对于爬虫的每次请求而言&#xff0c;这相当于 AWS Lambda 的每次函数的运行。 AWS Lambda 是一种将脚本部署到云的简单且价格低廉的服务&…...

认识Cesium旋转大小变量

前文代码中有如下&#xff1b;矩阵乘以旋转大小&#xff0c;还放入mat&#xff1b; Cesium.Matrix4.multiply(mat, rotationX, mat); 初看以为rotationX是一个数值&#xff0c;因为矩阵可以和数相乘&#xff1b; 但是看它的代码&#xff0c;rotationX是由一长串代码获得的&a…...

异响加持、吐槽声不断,小鹏G9难解困局

小鹏汽车的烦恼就好比红尘中的三千青丝&#xff0c;小鹏G9“惊魂48小时”的恐慌还未平息&#xff0c;车门异响等问题就已经层出不穷&#xff0c;再次将小鹏汽车推上风口浪尖。 可以毫不客气的说&#xff0c;G9承载着小鹏汽车盈利的希望&#xff0c;但在原本处于上升之势的G9却…...

【react】react18的学习

一、安装 $ create-react-app [Project name]默认支持sass 二、核心依赖 react&#xff1a;react 核心 react-dom&#xff1a;用于开发渲染web 应用&#xff1b; react-scripts&#xff1a;封装webpack服务&#xff1b; "start": "react-scripts start&quo…...

Ep_操作系统面试题-什么是线程,线程和进程的区别

1. 一个进程中可以有多个线程,多个线程共享进程的堆和方法区 (JDK1.8 之后的元空间),但是每个线程有自己的程序计数器、虚拟机栈和 本地方法栈。 2.进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位 视频讲解: https://edu.csdn.net/course/detail/38090 点我…...

最流行的自动化测试工具,总有一款适合你(附部分教程)

前言 在自动化测试领域&#xff0c;自动化工具的核心地位毋庸置疑。本文总结了最顶尖的自动化测试工具和框架&#xff0c;这些工具和框架可以帮助组织更好地定位自己&#xff0c;跟上软件测试的趋势。这份清单包含了开源和商业的自动化测试解决方案。 1&#xff09;Selenium …...

Shell高级——进程替换vs管道

以下内容源于C语言中文网的学习与整理&#xff0c;如有侵权请告知删除。 1、问题引入 这里将Shell中的“进程替换”与“管道”放在一起讲&#xff0c;是因为两者的作用几乎类似。 进程替换&#xff1a;将一个命令的输出结果传递给另一个&#xff08;组&#xff09;命令。 管…...

国内有哪些支持定制化的低代码平台?

编者按&#xff1a;贴合企业业务需求的系统才是好系统&#xff0c;高程度的定制能力平台意味着可以提供更高契合度的产品&#xff0c;更好地匹配业务需求。本文介绍了国内支持定制化的老厂商低代码平台&#xff0c;具有源码交付、私有化部署、国产化、数据对接等优势。关键词&a…...

Altair 宣布将于3月举办 Future.Industry 2023 全球虚拟大会

Altair&#xff08;纳斯达克股票代码&#xff1a;ALTR&#xff09;近日宣布将于 2023 年 3 月 8 - 9 日 举办年度全球虚拟大会 Future.Industry 2023。旨在探索影响全球未来的新趋势&#xff0c;并深入探讨仿真、高性能计算 (HPC)、人工智能&#xff08;AI&#xff09;和数据分…...

react lazyLoad学习记录

react lazyLoad学习记录1.lazyLoad用处2.使用2.1 react-router-dom5版本写法2.2 react-router-dom6版本写法1.lazyLoad用处 默认例如首页&#xff0c;如果有好十几个甚至百个路由&#xff0c;react是会默认一下全部把路由组件一下全部加载的&#xff0c;极可能造成页面卡顿。r…...

29 openEuler管理网络-配置网络绑定

文章目录29 openEuler管理网络-配置网络绑定29.1 使用nmcli29.2 使用命令行29.2.1 检查是否已安装Bonding内核模块29.2.2 创建频道绑定接口29.2.3 创建从属接口29.2.4 激活频道绑定29.2.5 创建多个绑定29 openEuler管理网络-配置网络绑定 29.1 使用nmcli 创建名为bond0的绑定&…...

RTT 全志D1s RDC2022纪念版开发板开箱使用分享与折腾记录

原文链接&#xff1a;https://bbs.aw-ol.com/topic/3021/ 作者caoxuetian 1&#xff1a;开发板介绍 RTT D1s RDC2022纪念版开发板是一块基于全志科技RISC-V内核 芯片 D1S的小尺寸开发板&#xff0c;尺寸仅为5.5cm*4cm&#xff0c;能够已非常小的体积带来舒适的开发感受&#…...

24日常实习万得一面面径

文章目录分析与复盘面试题分析与复盘 应该将项目进行复习好的&#xff0c;两个项目都应该对简历写的那些进行复习&#xff0c;以为日常不问项目的一面。哭死… 面试题 1.自我介绍 2.为什么从土木转到开发&#xff0c;学习java有哪些途径 3.介绍下项目中你觉得最有设计的模…...

MySQL的DML和DDL操作(1)

这里介绍几种DML操作INSERT INTO——插入记录插入一条记录插入一条记录 INSERT INTO table [(column [, column . ])] VALUES(value [,value . ]); 例子&#xff1a; insert into student values( 1,"承太郎" )default charset utf8&#xff1b;插入多条记录插入多条…...

Kafka系列之:Kafka生产者和消费者

Kafka系列之:Kafka生产者和消费者 一、Kafka生产者发送流程二、提高生产者吞吐量三、Kafka消费方式四、Kafka消费者总体工作流程五、按照时间消费Kafka Topic一、Kafka生产者发送流程 batch.size:只有数据积累到batch.size之后,sender才会发送数据,默认16K。linger.ms:如果…...

Linux进程间通信:信号量(一)

前提知识 在介绍信号量之前&#xff0c;先来看看一些概念和一些简单的前提知识&#xff1a; 进程间通信的前提是让不同的进程看到同一份资源。于是&#xff0c;就有提出让这种资源成为一种公共资源的方法&#xff0c;方法的提出&#xff0c;导致了一种新的问题的出现&#xf…...

wordpress get_the_tag_list/今日新闻快讯

一、 1、 2路CAN接口&#xff08;MCP2515的1路&#xff0c;STM32F103C8T6自带的1路CAN&#xff09;&#xff0c;可以实现两路CAN的通信&#xff1b; 2、供电范围宽&#xff08;7-28v&#xff09;&#xff0c;采用可插拔式4位数码管模块进行显示&#xff0c;数码管模块采用2线…...

制造企业网站的建设目标/营销策略包括哪些方面

Linux上Nginx中开启SSL模块&#xff0c;配置Https访问方式一、Nginx简介二、主题业务背景三、Nginx实现Https方式前期准备SSL证书申请Nginx需要开启SSL模块四、Nginx中配置Https配置前介绍nginx.conf配置详情一、Nginx简介 1.Nginx是一款轻量级、高性能的web服务器/反向代理服…...

如何设计网站布局/站点

前言 公钥密码包含两个密钥,加密密钥和解密密钥,其加密密钥是可以公开的,解密密钥是不能公开的。公钥密码自1976年提出这个思想后就不断发展,其一般是基于数学上的一些困难问题所建造的,如rsa基于大整数分解的困难问题建立的,椭圆曲线是基于椭圆曲线上的离散对数困难问题…...

上海知名网站建设公司排名/网站模板定制

只需要改变字体为&#xff1a; 文泉驿点阵正黑 即可。 转载于:https://www.cnblogs.com/iamnewsea/archive/2011/02/12/1952574.html...

龙岗建设企业网站/什么是网络营销?

问&#xff1a; 你做这个研究有一些年头了&#xff0c;我侧重于关心这些付出会有哪些回报&#xff1f; 答&#xff1a;预期回报当然是有的。那就是建立一个智能软件社区&#xff0c;每一个贡献者(包括我&#xff09;通过别人的使用获得回报。至于回报的多少&#xff0c;最简单…...

苏州比较好的建筑公司/网站优化设计的基础是网站基本要素及每个细节的优化

1. 描述在MySQL中&#xff0c;当我们需要获取某张表中的总行数时&#xff0c;一般会选择使用下面的语句select count(*) from table;其实count函数中除了*还可以放其他参数&#xff0c;比如常数、主键id、字段&#xff0c;那么它们有什么区别&#xff1f;各自效率如何&#xff…...