Handler通信机制

目标:

1.Handler和Looper什么关系?

一个Looper对应一个MessageQueue,可以多个handler往MessageQueue发送消息。

2.一个线程有几个Handler?

3.Handler内存泄漏的原因?

4.使用Message时如何创建它?

5.子线程维护的Looper, 消息队列无消息时的处理方案是怎么样的?有什么用?

6.为什么主线程可以new Handler?如果想要在子线程new Handler,应该怎么办?

7.线程间通信原理是怎么样的?

8.Looper死循环为什么不会导致应用卡死?

9.既然可以存在多个Handler往MessageQueue中添加数据(发消息的各个Handler可能位于不用的线程),那么它内部是如何保证线程安全的?

一、Handler机制

1.1 Handler是什么?

Handler机制是Android提供的消息通信机制。

它涉及多个关键组件,包括Handler、Looper、MessageQueue和Message,共同协作以实现消息的发送、接收和处理。

Handler:负责发送消息和处理消息。当发出一个消息后,首先进入一个消息队列,发送消息的函数即刻返回,而另一个部分在消息队列中逐一将消息取出,然后对消息进行处理。这种机制通常用来处理相对耗时比较长的操作。
Looper:负责循环读取MessageQueue中的消息,读到消息之后就把消息交给Handler去处理。
MessageQueue:存储消息对象的队列。
Message:消息对象,是Handler机制中传递的基本单位。

1.2 Handler工作原理

Handler机制的工作流程大致如下:

1) 创建Handler:首先需要创建一个Handler对象,其构造函数中的参数如async和callback用于确定消息的处理方式。async参数确定用Handler发送的消息是否要设置成异步消息,而callback参数则允许在dispatchMessage回调时优先调用callback中的代码。
2)发送消息:通过调用Handler的sendMessage或post等方法发送消息到MessageQueue中。
3)处理消息:Looper循环读取MessageQueue中的消息,并将它们分发给相应的Handler进行处理。处理过程包括调用Handler的handleMessage方法(如果存在回调,则优先执行回调)。
Handler机制在Android开发中特别重要,因为它允许在主线程中更新UI,同时避免阻塞主线程。通过在子线程中执行耗时操作,并通过Handler将结果发送回主线程进行UI更新,可以实现线程间的有效通信和UI的平滑更新。

二、线程间内存共享

MessageQueue是线程间共享的消息容器,用于管理消息。

完成线程间通信的原理:内存共享,通过共享MessageQueue消息队列,实现主线程和子线程通信。

三、消息Message

3.1 消息排序

按照msg.updateTime进行排序,相对于系统开机时间的时间戳。

3.2 消息创建

消息创建采用享元模式,增加消息对象复用。

1)消息存在一个缓冲池sPool(大小为50个),缓存使用完的消息对象;

2)创建消息的时候,优先从sPool中拿取一个消息对象;

3)消息使用完成后,将消息字段重置,然后添加到sPool,用于复用。

四、Handler内存泄漏和解决方案

4.1 Handler内存泄漏的原因

内存泄漏原因:JVM回收的时候问题,根可达算法,被JVM GC Roots直接或者间接引用的对象不能够被回收。

Activity中,

Handler handler = new Handler();

handler是一个匿名内部类,持有Activity的this对象;

ActivityThread的

static sMainLooper: 是一个静态变量,作为GC Roots

static sThreadLocal->Looper-->MessageQueue-->Message-->Handler-->Activity

msg.target = this;(Handler)

采用delay发送的消息,引用链仍然存在。

4.2 解决内存泄漏的方法

打断引用链。

1.Handler声明为静态内部类对象,不持有Activity引用

2.Handler采用弱引用Activity对象

Looper执行的动力:线程提供的。

EventBus、Retrofit与主线程通信,都需要借助Handler

五、Handler如何正确创建

5.1 主线程

主线程为什么创建Handler不需要指定Looper?

Handler Handler = new Handler();

主线程main运行的时候,从主线程Looper.mainLooper()

5.2 子线程撞见

1)先创建Looper

创建以后,调用Looper.prepare()

Looper.prepare

2) 初始化Handler

3)Looper.loop()

5.3 子线程Handler  HandlerThread

封装了Handler

HandlerThread获取Looper

public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        boolean wasInterrupted = false;

        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    wasInterrupted = true;
                }
            }
        }

        /*
         * We may need to restore the thread's interrupted flag, because it may
         * have been cleared above since we eat InterruptedExceptions
         */
        if (wasInterrupted) {
            Thread.currentThread().interrupt();
        }

        return mLooper;
    }

为什么需要采用while

因为如果是别的线程唤醒,如果Looper还没有初始化,需要继续等待Looper初始化。因此需要采用while。直到Looper有值。 

wait挂起:挂起线程,并且释放锁

sleep: 

六、Handler多线程安全

消息入列

消息获取:MessageQueue.next()  拿取一个消息

多个Handler往MessageQueue发送消息,如何保证线程安全性。

6.1 存消息的时候

boolean MessageQueue.enqueueMessage(Message msg, long when)

采用加锁的方式

synchronized (this) {

6.2 取消息的时候

Message MessageQueue.next()

synchronized (this) {

存消息和取消息的时候,同步进行。

6.3 Loop与ThreadLocal

    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

Looper通过ThreadLocal进行缓存。

每个线程对应于自己的Looper。 

七、同步消息和异步消息

消息屏障:target==null的消息。保证异步消息优先执行(UI刷新优先)

异步消息:isAync=true是异步消息,用于UI刷新。view.scheduleTraversals

同步消息:

添加消息屏障:

postSyncBarrier: 插入一个消息屏障

removeSyncBarrier: 移除消息屏障

丢帧;

skip 30 frames!

八、Looper.loop死循环为什么不会发生ANR问题

等待和休眠

1)没有消息的时候,阻塞等待消息到来;

2)等待消息执行时间:没有到消息可执行时间,epoll机制进行超时等待。

8.1 epoll机制

涉及到I/O

select: 非租塞忙轮询方式。没有数据的会出现CPU空转,浪费资源。直到一系列I/O事件存在,但不知道是哪几个流存在事件。

epoll_wait: 有N个I/O事件,一个线程处理多个I/O事件。没有I/O事件的时候进行阻塞,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/701566.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

重生奇迹MU剑士介绍

剑士拥有过人的体力及华丽的剑术,加上属于近距离攻击型职业,就算没有其他角色的帮助也可自行锻炼。由于剑士是剑术的专家,所以无法学习魔法,但与其他角色组队冒险时,因优异的体力通常是担任先锋角色。剑士等级达到150级…

SSM 离散数学线上考试系统-计算机毕业设计源码83059

摘 要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,高校当然也不例外。离散数学线上考试系统是以实际运用为开发背景,运用软件工程原理和开发方法,采…

VB.NET实现上位机自动识别可用串口

在实际应用中有时会牵扯到挑选可用串口,比如上位机和从站设备使用Modbus RTU协议进行通讯时需要选择COM串口,每次启动连接前都在设备管理器查看较为麻烦,可以设置一个串口自动识别功能,如果选择了错误的串口还可以提示串口选择错误…

借助Historian Connector + TDengine,打造工业创新底座

在工业自动化的领域中,数据的采集、存储和分析是实现高效决策和操作的基石。AVEVA Historian (原 Wonderware Historian) 作为领先的工业实时数据库,专注于收集和存储高保真度的历史工艺数据。与此同时,TDengine 作为一款专为时序数据打造的高…

排名前五的 Android 数据恢复软件

正在寻找数据恢复软件来从 Android 设备恢复数据?本指南将为您提供 5 款最佳 Android 数据恢复软件。浏览这些软件,然后选择您喜欢的一款来恢复 Android 数据。 ndroid 设备上的数据丢失可能是一种令人沮丧的经历,无论是由于意外删除、系统崩…

【Redis】Redis常见问题——缓存更新/内存淘汰机制/缓存一致性

目录 回顾数据库的问题如何提高 mysql 能承担的并发量?缓存解决方案应对的场景 缓存更新问题定期生成如何定期统计定期生成的优缺点 实时生成maxmemory 设置成多少合适呢?项目类型上来说 新的问题 内存淘汰策略Redis淘汰策略为什么redis要内存淘汰内存淘…

Echarts自定义地图显示区域,可以显示街道,小区,学校等区域

🚀🚀​​​​​​​🚀​​​​​​​目录 自定义地图 1. 选择边界生成器 2.导出JSON,在vue中使用: 3. vue中使用自定义地图 4.两个面、两条线,4个features,在每一个properties中添加name属…

英语四六级考试听力同频无线转发系统在上海电子信息职业技术学院的应用

英语四六级考试听力同频无线转发系统在上海电子信息职业技术学院的应用 由北京海特伟业科技有限公司任洪卓发布于2024年6月12日 一、 英语考试听力同频无线转发系统建设背景 英语听力考试作为评估大学生英语能力的重要一环,其顺利进行对于保障考试公平性和学生权益…

6月报名 | 海克斯康Actran风机类气动噪声分析培训

您好!感谢您长期以来对优飞迪科技与海克斯康的关注与支持。我们诚邀您参加海克斯康Actran风机类气动噪声分析培训,特邀海克斯康原厂讲师将以实操为基础,结合真实案例,手把手帮您解锁噪声仿真关键技术。 活动主题: 海…

金石传拓非遗技艺端午专场活动之精彩瞬间

6月10日端午节下午,由致公党润州区基层委二支部举办的“凝心铸魂强根基,端午追远贺盛世”金石传拓体验活动在镇江万达广场隆重举行。近30名党员及其家属参加了本次活动,活动由润州区二支部主委吴娉主持。 端午节,又称端阳节&#…

视频转换器推荐哪个好?多款视频转换器任你选

#快要溢出来的分享欲# 在数字化时代,视频已成为我们生活中不可或缺的一部分。无论是观看电影、学习课程还是记录生活,视频都扮演着重要角色。 然而你也知道,现在的视频格式五花八门,想在不同的设备上播放,就得转换格…

加速下载2024IDM下载器让网速飞起来!

网速慢,文件大,下载难。 这或许是很多人的上网日常。 尤其是当下载进度达到99.8%时,突然提示你下载失败,需要重新来过…… IDM马丁版下载如下: https://wm.makeding.com/iclk/?zoneid34275 idm最新绿色版一键安装包链接&#…

潇洒郎: 腾讯DDNS域名解析, DNSPod API使用示例—实时更新本地IPV6地址到DNS解析

1、新人一元购买一个域名 (到期后换身份,对于小白来说,玩玩域名而已,家人的身份就足够用几年了) 2、域名操作 查看我的域名信息 点击管理DNS解析 点击解析 如果之前有解析记录,则可导出 下载解压 查看一下

【NoSQL数据库】Redis Cluster集群(含redis集群扩容脚本)

Redis Cluster集群 Redis ClusterRedis 分布式扩展之 Redis Cluster 方案功能数据如何进行存储 redis 集群架构集群伸缩向集群中添加一个新的master节点,并向其中存储 num10 .脚本对redis集群扩容缩容,脚本参数为redis集群,固定从6001移动200…

简单记录常用五大机器学习模型

一、线性回归模型 线性回归模型是机器学习中一种基本且常用的回归预测模型。它主要用于预测连续值输出,例如房价、气温、用电量等。 1.1 基本原理 线性回归模型主要是尝试找到一种特征值(自变量)和目标值(因变量)之间的线性关系。模型的数学表达式为: 其中,是目标值,…

数字图像处理系列 | 通过相关性进行模板匹配 (5)

文章目录 1. 模板匹配模板匹配的公式表示 2. Convolution vs. Correlation3. Problem with Cross-Correlation4. 解决办法: Normalized Cross-Correlation: en5. 图片举例加深理解6. 参考书 1. 模板匹配 模板匹配的公式表示 CROSS-CORRELATION 2. Convolution vs…

【linux】-- 网络基础

计算机网络背景 网络发展 独立模式:计算机之间相互独立 网络互联:多台计算机连接在一起,完成数据共享 局域网(LAN)Local Area NetWork 广域网(WAN)Wide Area NetWork 所谓局域网和广域网…

传承产品的生命力与数字营销的魔法!

传承,是时间的沉淀,是文化的延续。具有传承特征的产品,犹如一颗闪耀的明珠,散发着独特的魅力。而在数字时代的浪潮中,我们又该如何发挥这传承的优势,赋予它新的增长价值呢? 具有传承特征的产品…

候选CVPR 2024最佳论文!深圳大学联手香港理工发布MemSAM:将 「分割一切」模型用于医学视频分割

根据世界卫生组织 (WHO) 的统计数据,心血管疾病是全球死亡的主要原因,每年夺走约 1,790 万人的生命,占全球死亡人数的 32%。超声心动图是用于心血管疾病的超声诊断技术,由于其便携性、低成本和实时性,被广泛应用于临床…

Linux 基本指令1

ls指令 ls【-选项】【目录或文件】当不指定目录或文件时指令能列出当前目录下所有文件除隐藏文件 选项: -a 列出所有包括隐藏的文件-隐藏文件以.开头。 -d 将目录如文件般显示-一般用ls显示目录是显示其目录中所有文件,加-d则显示目录的信息 -r 以反…