handler解析(5)常见面试题

news2024/9/21 22:00:11

目录

 

1.请大致讲下handler的工作原理 

2.handler.postDelay原理

3.一个线程有几个Looper?几个Handler?

4. Handler内存泄漏原因?以及解决方案

5.为何主线程可以new Handler如果想要在子线程中new Handler要做些什么准备?

6.消息退出是调用什么

7.loope死循环为什么不会造成应用卡顿

8.post跟send的区别


1.请大致讲下handler的工作原理 

handler的工作流程基本包括handler、message、message queue、looper这4个部分,

其中handler是消息的处理者,具备发生、处理、获取等功能,

message消息实体,可以带数据obj,行为标志符what和一串动作Runable,其中Runable转为了message的callback变量。

message queue消息队列,以队列的形式对外提供插入和删除操作,内部实际是一个单链表的数据结构,其中的消息的插入是根据传入的when进行插入的,when最短的插入到头部,时间最长的插入到尾部,其余消息根据when的大小对消息进行排序插入,遵循先进先出的原则。

looper,循环,它负责从消息队列中取出消息,然后把消息交给handler来处理

处理流程就是handler通过调用sendMesssage,实际是调用sendMessageAtTime发送when为0+当前手机启动到现在的时间为0到消息队列中的enqueue方法进行处理,消息队列检测到有消息后,判断当前when是否为0,或者when是否要小于于链表头个消息的when,或者当前没消息,这几种情况下就把message插入到链表头,然后唤醒looper,调用next方法获取链表头消息,分发个msg.targer进行dispatchMessage处理,然后判断msg中是否有runable,如果没有的话,就执行handlerMessage了

2.handler.postDelay原理

这块在上篇文章handler解析(2) -Handler源码解析_沙滩捡贝壳的小孩的博客-CSDN博客已经了解过了handler.postDelay本质上都是调用handler.sendsendMessageDelayed,然后调用sendMessageAtTime,最后调用enqueueMessage,然后我们知道MessageQueue会根据post delay的时间排序放入到链表中,链表头的时间小,尾部时间最大。在next取消息的时候,拿当前时间跟链表头的时间做对比,如果头部msg是有延迟的,而且延迟时间还没到的,则进行阻塞,然后等于是开了个定时器,等到时间到了的话,则进行唤醒操作,然后进行next操作取出消息,进行分发

举例:

  1. postDelay()一个10秒钟的Runnable A、消息进队,MessageQueue调用nativePollOnce()阻塞,Looper阻塞;
  2. 紧接着post()一个Runnable B、消息进队,判断现在A时间还没到、正在阻塞,把B插入消息队列的头部(A的前面),然后调用nativeWake()方法唤醒线程;
  3. MessageQueue.next()方法被唤醒后,重新开始读取消息链表,第一个消息B无延时,直接返回给Looper;
  4. Looper处理完这个消息再次调用next()方法,MessageQueue继续读取消息链表,第二个消息A还没到时间,计算一下剩余时间(假如还剩9秒)继续调用nativePollOnce()阻塞;
  5. 直到阻塞时间到或者下一次有Message进队;

3.一个线程有几个Looper?几个Handler

这块在上篇文章handler解析(2) -Handler源码解析_沙滩捡贝壳的小孩的博客-CSDN博客也说过了,一个线程只能有一个looper,这块是由ThreadLocal中ThreadLocalMap控制的,在loop.prepare中ThreadLocal进行set一个looper对象操作,而且ThreadLocal是static final类型的,但是handler就可以有无数个了,因为只要它关联到当前线程的looper就行了,这块在handler的构造方法中进行了声明

4. Handler内存泄漏原因?以及解决方案

泄漏原因:
Handler允许我们发送延迟消息,如果在延迟期间用户关闭了Activity,那么改Activity会泄漏。这个泄漏是因为Message会持有Handler,而又因为Java的特性,内部类会默认持有外部类的引用,使得Activity会被Handler持有,这样最终就会导致Activity泄漏。

解决方法:

静态内部类 + 弱引用

   private static class MyHandler extends Handler {
        //弱引用,在垃圾回收时,activity可被回收
        private WeakReference<MainActivity> mWeakReference;

        public MyHandler(MainActivity activity) {
            this.mWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    }

5.为何主线程可以new Handler如果想要在子线程中new Handler要做些什么准备?

每一个handler都要对应一个looper,主线程因为在AcitivityThread中的Looper.prepareMainLooper中已经创建好looper了,所以在new Handler中会直接通过ThreadLocal.get方法获取到looper。但是子线程就没有创建好looper了,所以在new handler的时候会因为ThreadLocal.get获取不到looper报错,所以需要在new Handler之前调用Looper.prepare();在之后调用Looper.loop(); Looper.myLooper().quitSafely();

6.消息退出是调用什么

消息退出是调用Looper的quit或者quitSafely,其中quitSafely()与quit()方法的区别是,quit()会直接回收消息队列中的消息,而quitSafely()会根据当前的时间进行判断,如果消息的meesage.when比当前时间大,那么就会被回收,反之仍然被取出执行。然后这个时候在发送消息时,消息是会被回收的

7.loope死循环为什么不会造成应用卡顿

线程对于java代码来说就是一段可执行代码,当可执行代码执行完了之后,程序就终止了,所以对于主线程来说,肯定不想就这么终止,所以死循环是必要的,可以保证一直执行下去,其次应用卡顿是在生命周期中执行耗时操作导致掉帧,甚至发生ANR,looper.loop本身是不会导致应用卡死的

再者说了,主线程的死循环一直运行是不是特别消耗CPU资源呢? 其实不然,这里就涉及到Linux pipe/epoll机制,简单说就是在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce()方法里,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。 所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。

8.post跟send的区别

post之前文章也分析过了,本质上还是调用sendMessageAtTime发送一条消息来着,只是说这条消息的赋值对象是msg.callBack,在next方法中优先执行.callBack中的方法,所以handler.post也可以用来直接在子线程中更新UI

send跟post本质上没有区别,post是send使用的简化版

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

R语言广义可加模型在空气环境污染方面的应用(1)

粉丝私信我希望复制一篇文章的图片&#xff0c;图片来源于文章&#xff1a;Wu C, Yan Y, Chen X, Gong J, Guo Y, Zhao Y, Yang N, Dai J, Zhang F, Xiang H. Short-term exposure to ambient air pollution and type 2 diabetes mortality: A population-based time series st…

中频采样和IQ采样的比较和转换

一、什么是中频采样&#xff0c;什么是IQ采样 射频接收系统通常使用数字信号处理算法进行信号解调和分析&#xff0c;因此需要使用ADC对信号进行采样。根据采样频率的不同&#xff0c;可以分为射频直接采样、中频采样、IQ采样。射频采样和中频采样只需要一路ADC&#xff0c;采…

搜索引擎ES相关问题

一、什么是倒排索引&#xff1f;有什么好处&#xff1f;索引&#xff1a; 从ID到内容。倒排索引&#xff1a; 从内容到ID。好处&#xff1a; 比较适合做关键字检索。 可以控制数据的总量。提高查询效率。搜索引擎为什么比MySQL查询快&#xff1f; lucence文章 -》 term ->排…

element-ui中el-table点击其他自定义按钮展开table中某一行

element-ui中el-table点击其他自定义按钮展开table中某一行 在日常开发中&#xff0c;我们遇见了会有点击某些按钮&#xff0c;使得表格行展开的需求&#xff0c;这时候去查看文档 element-ui&#xff08;table&#xff09; 这里官方提供了示例为在行最左侧有一个展开合并ico…

JAVA开发测试(jmeter如何测试性能与估算)

对C的业务网站或应用&#xff0c;进行性能测试来评估使用服务器情况是必不可少的一项工作。 一、测试工具&#xff1a; Apache JMeter 可以用于对服务器、网络或对象模拟巨大的负载&#xff0c;来自不同压力类别下测试它们的强度和分析整体性能&#xff0c;是Apache组织开发的…

CCF-CSP真题《202212-1 现值计算》思路+python满分题解

想查看其他题的真题及题解的同学可以前往查看&#xff1a;CCF-CSP真题附题解大全 试题编号&#xff1a;202212-1试题名称&#xff1a;现值计算时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 问题描述 评估一个长期项目的投资收益&#xff0c;资金的…

中点BH算法对任意斜率的直线扫描转换方法

作者&#xff1a;非妃是公主 专栏&#xff1a;《计算机图形学》 博客地址&#xff1a;https://blog.csdn.net/myf_666 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、算法原理二、…

六“元”数智增长模型,企业元宇宙时代的经营新范式

摘要&#xff1a;在中国传统哲学里&#xff0c;“元”表示最基本的、最根本的东西;在企业管理经营中&#xff0c;将“元”解释为企业的核心竞争力或者基础能力;元宇宙下&#xff0c;“元”就代表数智化下的新场景&#xff0c;来支撑企业的各种业务创新。 一、元宇宙下的“元” …

分享IDEA通过插件 【一键自动生成】 在线api接口文档

开发写代码已经很辛苦&#xff0c;相信每个开发人员都不想写接口文档&#xff0c;但是不写又不行。尤其现在开发的项目偏向于前后端分离&#xff0c;在没有接口的情况下&#xff0c;前后端很难对接联调&#xff0c;测试也无法很好的测试。现在IDEA的插件仓库里有款插件&#xf…

qt 内存泄漏处理办法

windows 版本windows msvc版本可以使用vld检测可以得到内存泄漏点的调用堆栈&#xff0c;如果可以的话&#xff0c;还可以得到其所在文件及行号&#xff1b;可以得到泄露内存的完整数据&#xff1b;可以设置内存泄露报告的级别。缺点&#xff1a;1.只针对 Visual C &#xff08…

VUE -- defineExpose

defineExpose定义demo定义 defineExpose定义&#xff1a;用于组件通信中父级组件调用操作子组建方法和响应式属性参数能力 在使用definExpose前需要了解两个拷贝对象函数 对象copy&#xff1a;shallowReactive 与 数据 copy&#xff1a;shallowRef 这两个都是vue包里面的 简…

图片文字识别OCR调研-中文

直接看效果对比 tesseract-ocr 该识别引擎最新版本tesseract4添加了支持神经网络&#xff08;LSTM&#xff09;的&#xff0c;该引擎专注于线条识别&#xff0c; 同时也保留了Tesseract OCR 引擎&#xff0c;该引擎通过识别字符模式来工作。 我们需求端的后台语言是go&#x…

时尚高级实用,零跑C01满足各种用车需求

零跑C01在新能源车市场上销量可观且口碑较好&#xff0c;为什么消费者会相中这个国产车全域自主研发的新能源车呢&#xff1f;下面的介绍会给出答案。就其外观而言&#xff0c;零跑C01的外观定位于中大型轿车&#xff0c;在外观设计上充分考虑到美学观念。零跑给出了七个车身颜…

扬帆优配|日均客运量恢复,民航业加速复苏,外资买入2股超亿元

春运民航客运量康复至疫情前七成。 2月16日&#xff0c;民航局举行2月例行新闻发布会。会上介绍&#xff0c;自1月7日至2月15日&#xff0c;春运40天&#xff0c;民航运送旅客5523万人次&#xff0c;日均客运量138万人次&#xff0c;同比去年春运添加39%&#xff0c;康复至2019…

Lesson5.1---Python 之 NumPy 简介和创建数组

一、NumPy 简介 NumPy&#xff08;Numerical Python&#xff09;是 Python 的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵&#xff0c;比 Python 自身的嵌套列表&#xff08;nested list structure&#xff09;结构要高效的多&#xff08;该结构也可以用来表示…

【贰】嵌入式系统的分类

随手拍拍&#x1f481;‍♂️&#x1f4f7; 日期: 2022.08.31 地点: 杭州 介绍: 2022.08.31下午一点&#xff0c;在闷热的学校里实在是待不下去了&#xff0c;跑到了门口的钱塘江边散了一会儿步&#x1f6b6;正值盛夏&#xff0c;八月即将完结&#xff0c;日子越过越快&#x1…

FPGA MAX 10 10M50系列10M50DAF484C8G/10M50DAF484C7G/10M50DCF484C7G规格

介绍MAX 10器件是单芯片、非易失性低成本可编程逻辑器件(pld)&#xff0c;用于集成最优的系统组件集。MAX 10设备的亮点包括:内部存储双配置闪存用户闪存即时支持集成模数转换器(adc)支持Nios II单芯片软核处理器MAX 10设备是系统管理、I/O扩展、通信控制平面、工业、汽车和消费…

ant design vue 组件中经常会出现 label过长被盖住的情况

ant design vue 组件中经常会出现 label过长被盖住的情况&#xff0c;我还特地找了解决方法&#xff1a;当过长时让他换行显示&#xff0c;还写了一篇博客记录&#xff0c;今天同样是写代码&#xff0c;但并没有做特殊的设置&#xff0c;结果却出乎意料的正常&#xff0c;过长自…

2023美赛A题:收干旱影响的植物群落(MCM)思路Python代码

赛题目的:分析干旱程度与植物群落中物种数量的关系赛题解读&解题思路链接: (1)这道题的难点是寻找数据,如果能找到干旱程度的适应性代表的指标以及对应植物群落物种的数量,那这道题基本上是迎刃而解,只需要简单去搭建一个预测模型即可仿真 (2)目标是对马萨马拉这个…

基于dll注入 读取任务管理器中指定进程的详细信息

关键字 注入dll&#xff0c;遍历ListView 技术调研背景 QA测试程序时&#xff0c;往往需要关注进程的性能指标&#xff0c;比如&#xff1a;CPU&#xff0c;GPU&#xff0c;内存&#xff0c;显存。最终根据各个采样数据&#xff0c;生成基于时间轴的状态表&#xff08;类似任…