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

字节面试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 就问了这么多了,大家可以好好的吸收一下~

杭州这所学校孩子和家长的快乐密码太阳好像吃了无数辣椒,张大嘴向地球哈着热气。操场上,十多个由高到低的影子,一圈又一圈刷着滚烫的塑胶跑道。额头上的汗珠子成群结队想把苦瓜脸磨平,让笑脸重回小主人们的身边。腿像绑了千斤今日鸡蛋价格重拾上涨,明日将会持续?明日鸡蛋价格预测关注鸡蛋价格每日行情开篇按照惯例,给您带来今日鸡蛋市场的最新行情动态根据最新数据显示今日全国鸡蛋最新平均价格5。40元斤,与昨日鸡蛋平均价格相比上涨0。01元斤,与上周鸡蛋平均价格人均50,在澳门吃到撑的快乐密码我知道朋友们,上周我们终于出去团建啦!这次的团建其实分成了云南和澳门两组(想知道这次编辑部的澳门团建有多抓马,可以期待一下在路上的团建文)。今年我们吸取了去年一犹豫就被困在杭州的悲惨教训远离痛风,多吃绿灯食物,少吃红灯食物有人体检发现尿酸超标,有人已确诊高尿酸血症,甚至有人已是痛风患者。那么,生活中如何吃才有助于降低尿酸值?前段时间,奥地利风湿病和康复学会对痛风和高尿酸血症患者的饮食和生活方式建议进Nike抛弃欧文,哪个品牌敢签约?欧文Nike解约,欧文球鞋不入手会起飞吗?欧文1代此时是欧文以状元郎的身份入主克利夫兰骑士队的第3年,欧文1代设计上与欧文华丽实用的球风形成了鲜明的对比,鞋身侧面简洁的Logo加上为什么很多衣服的拉链上会刻着YKK,到底是啥意思?如果你细心观察,会发现很多拉链上都刻有YKK的字样。这是什么意思呢?其实YKK是一个日本品牌。它是拉链行业的鼻祖,创立于1934年,日语写作吉田工業株式会社,而公司英文名译作Yos韩国女神韩素希韩剧泰剧迷有网友说今日韩素希出席活动,一身独特的抹胸裙真是漂亮,关键是这个墨绿色一般人驾驭不了。韩素希1994年11月18日出生于韩国,不仅是演员还是一名优秀的模特。这身抹胸墨绿色40岁的女性这样穿,减龄又时尚,羊羔绒搭配牛仔裤,时髦又洋气对于爱美的女性来说,羊羔绒大衣是必不可少的一件单品,羊羔绒保暖又显贵气,时尚还减龄,无论多大年龄段都是偏爱羊羔绒。羊羔绒外套占据了时尚少女衣橱的最高出镜率,羊羔绒最大的优点就是保暖冬季养生小知识,女孩们别划走冬天对很多宝贝儿们来说应该是最难熬的季节了,手脚冰凉,肠胃着凉,抵抗力下降,各种各样的小问题如雨后春笋般冒了出来,那么这份冬季养生大法您可要接好啦!多保暖,防犯病冬季气候诱使慢性病冬季旅游必去的十大美景,别有一番风味哦2022年的第一场冬雪来得有点早,天气也已经进入严寒状态,但是冬季所拥有的美景同样是不同小觑的!现在就带大家来看一看,冬季旅游必去的10大美景,准备出发吧,别有一番风味哦!10长白电动牙刷的优劣科普,警惕三大风险副作用个护博主李若发现大家对电动牙刷的评价有很大不同,有的人觉得电动牙刷很好用,有的人则是认为电动牙刷容易伤牙,就是智商税。为了让大家更全面的认识电动牙刷,今天我就来详细讲讲电动牙刷的优
稻盛和夫人往高处走,最重要的不是能力,而是自身的器量企业要发展,要求经营者努力提升自身的器量,换句话说,就是不断提升自己的心性哲学思维方式和人格。本文精选了稻盛和夫著作经营为什么需要哲学经营十二条(人民邮电出版社出版)企业家精神(机江西宜春2少年为救全车人与歹徒搏斗错过高考,8年后过得还好吗导读江西2位夺刀少年,因救全车人错过高考,8年后过得怎么样?近日,北京见义勇为人员高考加20分的政策引发了关注。据6月10日上午召开的新闻发布会得知,北京优待见义勇为人员,并在见义每晚喝一瓶啤酒,时间久了,身体会怎么样呢?医生告诉你答案啤酒是以小麦芽和大麦芽为主要原料,并加啤酒花,经过液态糊化和糖化,再经过液态发酵而酿制成的。其酒精含量较低,含有二氧化碳,富有营养。它含有多种氨基酸维生素低分子糖无机盐和各种酶。这一家七口全患癌!警告得了这5种癌症,可能遗传给下一代相信大家看过不少类似的新闻如宋庆龄宋美龄一家几乎都患上过癌症梅艳芳及其姐姐也都是因患宫颈癌而逝世为啥癌症会在家族中扎堆出现?这些在家庭中扎堆出现的癌症常被称为家族癌或夫妻癌LAMu桉树被称亡国树断子绝孙树缺德树,人类却还要种植,为啥?人类总是喜欢站在自己的角度,给自然界当中的许多生物起外号。这当中,有一种树就非常不受待见,它就是桉树。桉树林桉树常常被人们称为亡国树断子绝孙树缺德树,从这些外号来看,它应该是一种危美国5月CPI同比上涨8。6,创1981年底以来最大涨幅美国劳工部10日公布的数据显示,5月美国消费者价格指数(CPI)环比上涨1,同比上涨8。6。数据显示美国CPI同比涨幅再创1981年12月以来最大值。6月10日,顾客在美国纽约一家王洛勇曾是胡歌的恩师,独闯美国16年,感激19岁嫁给自己的丁宁1997年,王洛勇接受了导演夏刚的邀请,出演其执导的电影生命如歌。剧中,一位苏联的钢琴家,掷地有声地说出一个艺术家如果不为生他养他的土地去呐喊的话,他的作品永远没有灵魂,永远没有根张雨绮中国男人都该去服兵役,战狼精神都用来对付女人了唐山烧烤店打人事件成为近期焦点话题,一个女孩子拒绝流氓搭讪,被六七个壮汉拖出去暴打至重伤,现仍在医院抢救。人们愤怒于人渣竟可以残暴到这种地步,视她人生命如无物惊诧于社会风气之恶劣,专科生凭啥穿学士服?本科生吐槽大专生没资格,评论区吵翻天好好学习,将来考一所好大学,这是很多学生从小听家长念叨大的话,那个时候大学对学生来说是一种憧憬,而随着升上高中才发现,原来大学也有不同层次。每年临近毕业,大学生们除了要赶论文忙答辩唐山烧烤店多名男子围殴女生,气的我一夜未眠6月10日,网友发布网帖称河北唐山机场路一家烧烤店多人起冲突,疑因男子酒后搭讪骚扰一女子,后多人对女子进行殴打。看了完整视频,性骚扰遭女的反抗,就打人,一直冲着女的头来打!男人打女唐山事件令人深思,女生包里放这几样东西遇到危险时一定有用唐山烧烤店事件引起广大网友关注,目前受害女子伤势已有好转!主犯已经被抓获,这不得不给唐山办案民警点个赞,顶着社会的压力在短短几天内就把主犯抓住了。社会人多复杂那么如果我们在遭遇同样