zoukankan      html  css  js  c++  java
  • handler面试准备

    自我总结:

         从主体结构来讲主要是三部分,looper,Messagequeue,handle,looper中存在一个死循环不断从信息队列中取出信息交给对应的handle进行处理,主线程中的looper在App启动的时候就会启动,具体代码在activityThread的main方法中,因此在主线程中使用handle的时候不需要去管looper的创建,在子线程中使用handle需要调用looper.prepare.和lopper.loop来创建对应的looper,而looper和线程是一一对应的,一个线程只能拥有一个loop,这个实现是通过ThreadLocal来实现的,threadlocal简单的来说它线程私有的一个数据副本(这边可以扩展讲下threadlocal内存泄漏的原因以及优化处理),它是线程自身维护的一个key-value集合,这边key就threadlocal的对象,value就存放对应的值,thread创建对应的loop的threadlocal对象是静态final的变量,在内存空间里是唯一的存在,让key是唯一的存在,这样在线程创建loop的时候进行判断该key是否存在对应的值,如果有就抛出异常来。这样保证了thread有唯一的looper。messagequeue是一个存在优先级的单向信息队列,在messagequeue中它保存的是一个message的对象,而message对象它持有next message对象的引用 所以可以通过不断调用next我们可以遍历到整个message队列,所以队列是单向的,优先级实现的原理需要看put方法,handle的所有sendmessage方法最后调用都是sendmessageattime 这里会给每个message设置一个延时执行时间,在信息存入队列时从头开始遍历比较执行时间,如果比对方小就插入到对方前面,从而实现了优先级的队列,handle可能导致的内存泄漏也就在于此,一个延迟消息在messagequeue中存放,message会持有handle的引用,而handle是一个匿名内部类,在java中匿名内部类默认持有外部类的引用,最后导致handle所在的activity被持有而导致不能释放。如果当message队列为空或者当前最新的message延迟处理的话,当前线程会进入休眠状态,而这个休眠状态是通过native方法来实现的 底层调用了liunx的休眠方法,而休眠的时间由当前任务来决定的。handle为什么能跨线程处理任务的原因需要考虑java虚拟机的一些知识,(可以扩展讲java虚拟机)堆是线程共享的,所以message队列数据就存放在堆中,这就实现了handle跨线程通信的基础了,这里多线程并发操作肯定需要一个锁来维护资源的安全性,这里通过synchronized来实现多线程对信息队列访问的安全机制,(这边可以扩展锁相关信息)不管是添加还是取出message都会重置looper的休眠状态。message取出后调用对应的handler处理这样整个流程完成了。

     

    总结知识点:

    1.handler处理整体的结构。

    2.handler为什么能跨线程通信的。

    3.为什么looper里面一个死循环不会导致卡死问题。

    4.handler处理信息的优先级如何实现的。

    5.handler在多线程情况下怎么实现线程安全。

    6.looper和线程是如何一对一进行绑定的。

    7.为什么支持new 出多个handler。

  • 相关阅读:
    安装配置ssh免密码登录
    大数据学习之Linux环境搭建(导航)
    Linux下搭建sqli-labs环境
    SpringMVC freemarker 中 Could not resolve view with name 'XXX.ftl' in servlet with name 'SpringMVC'
    配置FreeMarker时IDEA提示cannot resolve property 'templateLoaderPath'
    MySQL在指定字段后添加一个新字段
    META-INF/MANIFEST.MF file not found in unnamed.war
    Java获取音频播放时长
    JS实现阿拉伯数字转韩文
    微信公众号开发-素材管理-调用接口返回结果一览表
  • 原文地址:https://www.cnblogs.com/fuccc/p/15084452.html
Copyright © 2011-2022 走看看