IntentService、HandlerThread与ThreadLoccal、ThreadLocalMap

    技术2022-07-10  91

    1、IntentService

    2、从上图看出是个服务,所以看下onCreate方法,初始化了一个HandlerThread对象,以及一个Handler,注意Handler传入的Looper对象是HandlerThread对象

    3、onStart方法 ,注意msg属性的赋值

     

    4、接下来看下onHandleIntent执行时所在的线程

    上面说了Handler传入的是HandlerThread中的Looper,那么HandlerThread是什么 呢?

    5、HandlerThread首先是一个线程

    6、之前有说过开启线程的方法之一就是继承Thread,新生成对象后调用start,会运行run方法

    7、IntentService赋值的looper是什么呢?,可以看出就是mLooper

    8、为什么调用wait,因为虽然上面我们调用了start但是线程此时只是就绪状态,而不是运行状态,只有拿到CPU使用权才可会运行run方法,这也是为什么HandlerThread要调用notifyAll的原因。不得不说每行代码都是宝啊

    9、IntentService中的Handler是HandlerThread中的looper,那么当消息队列中的消息执行时运行的线程就是开启的HandlerThread线程。为什么呢?

    我们看下Loop.prepare();做了什么操作?

    从上面代码看出获取线程中的ThreadLocalMap对象,如果为空就初始化,并放入第一个值

    而存入的key就是当前的ThreadLocal对象,value就是Looper

    10、再来看下Looper.loop();方法

    从上面代码看出获取当前线程的ThreadLocalMap对象,在获得以threadLocal作为key的entry然后获取value

    就是刚才存入的looper对象,在获取looper中的消息队列然后在获取msg最终执行了 msg中持有的target对象,就是IntentService中的Handler。具体请看Handler源码解析。所以说IntentService中的抽象方法是运行在子线程的

    11、ThreadLocalMap是实现的我们常见的Map吗?看代码就一目了然

    事实上他不仅没有实现Map,还和我们常见的Map在Hash冲突和数据结构有很大差异,首先它的key值总是ThreadLocal,在looper中ThreadLocal是静态变量(保证了一个线程一个looper),既然key类型一样,自然没有必要像Map那样处理Hash

    虽然每次生成新的对线下个对象的hash值会加上斐波拉契数列,但还是有可能产生hash碰撞处理和获取方法下面贴出代码

    另外特殊的是集合中存储的对象其key是弱引用

    而对于value的内存泄漏是每次set或get时未能成功命中目标节点,发现key为null时对该节点删除从而释放value

    Processed: 0.013, SQL: 9