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