范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

字节面试6连问讲讲ThreadLocal与Handler

  作者:冬日毛毛雨
  https://juejin.cn/post/7160681836291555365   一问:讲讲 ThreadLocal 和 Handler 的关系
  竟然提到了 Handler 机制就不得不提到这几大将了:Handler,Looper,MessageQueue,Message。延伸重点 ThreadLocal !!
  当 UI 的主线程在初始化第一个 Handler 时,就会通过 ThreadLocal 创建一个 Looper,该 Looper 与 UI 主线程一一对应。而使用 ThreadLocal 的目的是保证每一个线程只创建唯一一个 Looper。Looper 初始化的时候会创建一个消息队列 MessageQueue。至此,主线程、消息循环、消息队列之间的关系是 1:1:1。
  Handler、Looper、MessageQueue 的初始化流程如下图所示:  Hander 持有对 UI主线程消息队列 MessageQueue 和消息循环 Looper 的引用  子线程可以通过 Handler 将消息发送到UI线程的消息队列 MessageQueue 中。
  二问:主线程为啥不用初始化 Looper 呢?
  因为 Looper 早在 ActivityThread 初始化的时候就声明好了,可以直接拿来用。通过分析源码我们知道 MessageQueue 在 Looper 中,Looper 初始化后作为对象丢给了 Handler,并且又存在了 ThreadLocal 里面,ThreadLocal 和 Looper 作为 k,v 存在了ThreadLocalMap,ThreadLocalMap 属于当前 Thread,也就是说 Looper 作为桥梁连接了 Handler 与 Looper 所在的线程。
  可以理解为 Looper 关联了 Handler 和当前线程  三问:Handler 机制有了解过没?跟我说说?
  在理解 Handler 机制前,我们需要先搞懂 ThreadLocal。
  ThreadLocal 叫做线程变量,意思是 ThreadLocal 中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal 为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
  想搞懂原理那就得先从源码入手开始分析。我们先从 set 方法看起:
  从上面的代码不难看出,ThreadLocal#set 赋值的时候首先会获取当前线程 thread,并获取 thread 线程中的 ThreadLocalMap 属性。如果 map 中属性不为空,则直接更新 value 值,如果 map 中找不到此 ThreadLocal 对象,则在 threadLocalMap 创建一个,并将 value 值初始化。显然 ThreadLocal 对象存的值是根据线程走的!
  那么 ThreadLocalMap 又是什么呢,还有 createMap 又是怎么做的:
  每个 Thread 有一个属性,类型是 ThreadLocalMap,从代码不难看出 ThreadLocalMap 是 ThreadLocal 的内部静态类。它是与线程所绑定联系在一起的,可以看成一个线程只有一个 ThreadLocalMap 。
  ThreadLocalMap 的构成主要是用 Entry 来保存数据 ,而且还是继承的弱引用。在 Entry 内部使用 ThreadLocal 对象作为 key,使用我们设置的对象作为 value。
  get 比较简单,就是获取当前线程的 ThreadLocalMap 属性值,在获取 Map 中对应 ThreadLocal 对象的 value 并返回。
  对 ThreadLocal 做一个总结:每个线程 Thread 自身有一个属性 ThreadLocalMap,这是一个键值对,它的 key 是 ThreadLocal 对象,value 是我们想要保存处理的数据值。getMap 是找到对应线程的 ThreadLocalMap 属性值,然后通过判断可以初始化或者更新数值。
  ThreadLocal 分析完了我们接着来看 Handler 。
  因为主线程在 ActivityThread 的 main 方法中已经创建了 Looper,所以主线程使用 Handler 时可以直接 new;子线程使用 Handler 时需要调用 Looper 的 prepare 和 loop 方法才能进行使用,否则会抛出异常。所以我们从 Looper 的 prepare 来分析。
  Looper 提供了 Looper.prepare() 方法来创建 Looper ,并且会借助 ThreadLocal 来实现与当前线程的绑定功能。Looper.loop() 则会开始不断尝试从 MessageQueue 中获取 Message , 并分发给对应的 Handler,也就是说 Handler 跟线程的关联是靠 Looper 来实现的。
  Looper.loop() 负责对消息的分发,也是和prepare配套使用的方法,两者缺一不可。
  msg.target 是个啥呢,我们追到 Message 里面不难发现其实它就是我们发送消息的 Handler,这写法是不是很聪明,当从 MessageQueen 中捞出 Message 后,我们就能直接调用Handler 的 dispatchMessage,然后就会走到我们的 Handler 的 handleMessage 了。直接上源码:
  Handler 提供了一些列的方法让我们来发送消息,如 send() 系列 post() 系列 。不过不管我们调用什么方法,最终都会走到 MessageQueue的enqueueMessage(Message,long) 方法。也就是将 Message 插入到我们的 MessageQueue 中。
  dispatchMessage() 方法针对 Runnable 的方法做了特殊处理,如果 msg.callback !=null则会直接执行 Runnable#run()
  MessageQueue是个单链表。MessageQueue里消息按时间排序。MessageQueue的next()是个堵塞方法
  总结分析:Looper.loop() 是个死循环,会不断调用 MessageQueue.next() 获取 Message ,并调用 msg.target.dispatchMessage(msg) 回到了 Handler 来分发消息,以此来完成消息的回调。  四问:Handler 什么会出现内存泄漏问题呢?
  Handler 使用是用来进行线程间通信的,所以新开启的线程是会持有 Handler 引用的,如果在Activity 等中创建 Handler,并且是非静态内部类的形式,就有可能造成内存泄漏。
  非静态内部类是会隐式持有外部类的引用,所以当其他线程持有了该 Handler,线程没有被销毁,则意味着 Activity 会一直被 Handler 持有引用而无法导致回收。
  MessageQueue 中如果存在未处理完的 Message,Message 的 target 也是对 Activity 等的持有引用,也会造成内存泄漏。
  解决办法: 使用静态内部类 + 弱引用的方式:静态内部类不会持有外部类的的引用,当需要引用外部类相关操作时,可以通过弱引用还获取到外部类相关操作,弱引用是不会造成对象该回收回收不掉的问题,不清楚的可以查阅JAVA的几种引用方式的详细说明。
  在外部类对象被销毁时,将 MessageQueue 中的消息清空。  五问:Looper 死循环为什么不会导致应用卡死?
  对于线程即是一段可执行的代码,当可执行代码执行完成后,线程生命周期便该终止了,线程退出。而对于主线程,我们是绝不希望会被运行一段时间,自己就退出,那么如何保证能一直存活呢?简单做法就是可执行代码是能一直执行下去的,死循环便能保证不会被退出,例如,binder线程也是采用死循环的方法,通过循环方式不同与 Binder 驱动进行读写操作,当然并非简单地死循环,无消息时会休眠。
  但这里可能又引发了另一个问题,既然是死循环又如何去处理其他事务呢?通过创建新线程的方式。真正会卡死主线程的操作是在回调方法 onCreate/onStart/onResume 等操作时间过长,会导致掉帧,甚至发生ANR,looper.loop 本身不会导致应用卡死。  六问:主线程的死循环一直运行是不是特别消耗CPU资源呢?
  其实不然,这里就涉及到Linux pipe/epoll 机制,简单说就是在主线程的 MessageQueue 没有消息时,便阻塞在 Loop 的 queue.next() 中的 nativePollOnce() 方法里,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往 pipe 管道写端写入数据来唤醒主线程工作。
  这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。
  好了,这轮面试中问道的Handler 就问了这么多了,大家可以好好的吸收一下~

黑豹乐队将在太舞滑雪小镇与两千名青少年歌手乐手共唱经典四方签署合作协议北京音协供图中新网北京3月26日电(记者应妮)北京音协会摇滚音乐分会乐队中国LEAFPARTY现代音乐派对崇礼太舞滑雪小镇黑豹乐队四方25日在京签署战略合作协议,宣和珅成就王刚,六小龄童垄断孙悟空,这些演员一个角色吃一辈子如今,多数演员的职业生涯中,有些人因为一个角色得到了尊重和赞扬,但也有些人不自重,长时间消费角色被人嫌弃。下面介绍三位被观众嫌弃,一个角色吃一辈子的演员。第一位是王刚,他因出演电视经典剧连载23穷人家女孩爱上王子,怎料婚后竟产下一枚白蛋开始阅读之前,麻烦您动动手指点个关注,方便我们讨论和交流,感谢您的支持,您的阅读和关注是我持续更新的动力!这个女人肚子疼的打滚,下一秒竟生了枚白蛋。白蛋掉在地上,女人想让姐姐把孩子试驾零百加速3。9秒,续航超1100km,哪吒S靠实力说话记者刘庆义目前,无论对标豪华品牌,还是日系合资品牌各自的销量担当,新能源车都形成了不小的优势。相比燃油车时代的定价体系,国内的新能源车可谓是配置给到顶,价格给到底。而在这样的竞争之带娃搭飞机请留意三要一注意,这份指南请收好最是一年春好处,踏青出游正当时。近日,不少家长携带儿童乘机出行,但有个别家长因不了解儿童乘机规定,到达机场后才发现儿童未购票未值机。白云机场安检部门温馨提醒广大旅客婴儿(儿童)乘机用三秒干一天的活,ChatGPT已能骗过亚马逊一些跨境电商卖家将跨境电商神器的殊荣给到了横空出世的ChatGPT。用三秒完成我一天的活。出现在了一位跨境电商卖家的分享文案中,许多卖家相信,ChatGPT会改变行业。在OpenA干货亚马逊单量下降该如何补救近期很多亚马逊卖家反馈,3月的单量一直不温不火了,也不知道哪个方面出现了问题。今天就单量下降问题,我们做一个全面的分析,然后大家可以对应核查是哪方面原因造成的,相应的做出举措提升单亚马逊每日一店ampampamp130销售家具类商品,苏州卖家月赚70万今天介绍的这位卖家,主要经营家具类产品。品牌Walensee产品数量69Feedback永久的是8700多个,近一个月约161个预计订单量日订单量1500多单月度销售额70w美金月引入东风资管和重科控股,驭势科技完成数亿人民币C轮融资编辑丁琳近日,前沿无人驾驶解决方案提供商驭势科技(北京)有限公司(以下简称驭势科技)正式宣布完成数亿人民币C轮融资,此轮由东风资管及重庆高新开发建设投资集团旗下重科控股共同参与投资华为P60系列支持数字人民币无电支付没电没网也不怕TechWeb日前,华为在上海召开了期待已久的新品发布会,全新的华为P60系列和MateX3两大旗舰正式登场。其中华为P60系列首发双向卫星通信夜视长焦,首发搭载全新鸿蒙3。1,在WOT新车丨人民币56元月租的坦克M系8金重坦TS54当前数据本文首发于微信公众号坦克零距离,文章转载权限坦克空间站UP为个人专栏文章作者,非官方人员,在头条同步更新文章原来它是为了这个啊各位车长老爷们大家好啊,我是阿纳贝尔丶卡多。在去年的时
太原的青龙古镇里面有什么好玩的?谢邀太原现有二千多年历史,而青龙古镇现保存明清以前古门亭城门墙宽大古商铺街多种多样豪华古建筑群,是难中华文物古迹文化遗产,是旅游(好玩)了解古时候文化而南岭少数民族比中原文化发展迟数字人民币做出决定,放弃阿里选择京东,意味着什么?毫无疑问,京东的家国情怀确实要比阿里强太多了!刘强东返乡报恩,有情有义!刘强东对待职工,亲如家人,企业文化深厚,企业发展的潜力巨大。刘强东重资产建立京东生态,不是纯粹的电商企业,更用户运营是什么?感谢悟空邀请。很多人将产品技术营销和运营混在一起,谈营销也是运营,谈产品也是运营。他们之间有什么关系,是不是毫无关系,又或者混为一谈?首先要能知道,运营到底什么一回事。什么是运营?一级建造师考了2年还没有考过,很打击信心,该怎么办好?非常感谢你的邀请,我来回答你的问题。目前你剩下的两门科目是建筑实务课和经济,在前两年学习的基础上,总结一下,再按照我下文提到的方法去学习,拿出你第一年备考一建的劲头,相信你一定可以肠镜多长时间做一次好?先说结论肠镜要根据之前检查的情况和病史及家族遗传史去决定检查的频率,一般的推荐检查或复查频率在半年至10年之间不等,要具体情况具体分析。最近看到了很多关于肠镜检查的问题,因为肠镜检怀孕后什么时间去做第一次产检?怀孕了,孕妈妈最关心的就是胎宝宝长得怎样了,自己的身体是否安好。但孕妈妈和胎宝宝隔着一层肚皮,需要产检才能获得答案。定期产检,能监测孕妈妈和胎宝宝的健康状况,及时发现问题及早防治,如果你被隔离1个月,只有一部老年机,你会怎么样?我会看小说这难不倒我,用笔用纸记录下每天隔离生活的过程,记录下每天心里活动情况,坚持记录30天,出来后立即上今日头条发表文章,立马粉丝暴增给你带来意想不到的结果呲牙呲牙呲牙会归自然祖母绿为什么这么贵?以后别盯着黄金咋咋呼呼,好贵啦!提高认知,不要表现得好像没见过大世面似的,保持淡定!看完这篇文章,告诉你什么才是珠宝界的实力担当。今天我们聊一聊祖母绿,你凭什么这么贵?国际公认的名你觉得王者荣耀峡谷中养鸡流这个玩法怎么样?在前段时间的时候,什么献祭流送死流养猪流风靡王者峡谷。除了养猪流之外,近期又突然出现了另外一种玩法,那就是养鸡流啦,这个玩法看起来和养猪流有一些相似的地方,其实完全不太一样,因为这老詹跟死神,退役后,谁的历史地位会更高?当然是詹姆斯的历史地位更高,这个没有任何争议,都不带一点犹豫和思考的。首先,从荣誉上看,衡量一个球员成就大小最重量级的两个奖项,MVP和FMVP,詹姆斯就有44个,而阿杜才12个!家里安装了电信带宽为300M的光纤,网速却慢如蜗牛,怎么解决?现在宽带速度越来越大,套餐有100M300M500M1000M,如果配套设备跟不上或网络设置的不好,都会导致网速不达标。我是网络工程师陈锋,拥有10年互联网维护经验,我来跟大家详细