“阅读本文大概需要2分钟。”
看小张有些受惊,我打算换个新的角度。
继续问道:刚才说到每个线程只能有一个唯一的looper,你知道android是怎么保证这一点的吗?
小张眼睛躲避着我的视线,模糊的回答道:我好像记得有个threadLocal和这个有关。
为了给小张一点鼓励,我说道:没错,你说对了,就是它!
小张感觉打了一针强心剂。
我继续问道:那threadLocal是怎么做到的呢,你能说具体一点吗?
小张:我记得threadLocal里面的核心就是一个hashmap,用来保证的。
我来了兴趣,继续问:那这个hashmap里的key和value分别是什么能达到这个目的?
小张开始支支吾吾...过了一会儿说道:value里存的是looper对象,key存的是...
看到小张期待求助的眼神,我继续提示道:你想想key用什么能够保证线程和looper的唯一映射?肯定是唯一代表线程的东西,对吧?
小张:哦,要是我来设计,会用thread本身来当key来保证这一点。
我看小张还是不很确定,就肯定的说道:没错,threadlocal正是用的thread对象本身来当key[注1],这样每次在thread里创建一个looper时,系统都会先去全局的threadLocal里的hashmap看看对应的线程里是否已经存了looper,如果没有,就说明这个线程还没有创建过looper,就正常创建,然后存进hashmap里。如果已经有了,就会报错。如此一来,每个线程就像在自己的环境里保存本地变量一样,互不干扰,这也就是Local的意思。
为了考察小张的学习能力,我又问道:那你觉得threadlocal一般能够使用在哪些场景呢?它和锁在使用场景上有啥区别啊?
小张这次没有让我失望,回答道:当开发过程中需要一个全局变量能够在多线程场景中使用,而且互不干扰,可以定义一个threadlocal即可,而无需为每个线程定义一个全局静态变量,使用起来非常方便。锁就不一样了,它是为了保证一个变量在不同的线程之间共享而存在的控制手段。简而言之,一个是线程独立,一个是线程共享,场景不同。
听到这个回答我内心是非常赞赏的,但是作为一名合格的面试官,必须不露声色。
继而又问:既然looper是通过threadlocal保证了唯一性,那message queue[注2]唯一性又是如何保证的呢?
小张这次笑了:这个简单,由于message queue是looper里的一个属性,looper是线程唯一的,所以message queue也是线程唯一的。
我点了点头,对小张一轮战绩表示了肯定。
小张感叹道:没想到面试还能学习到这么多知识啊...
未完待续...
[注1]:真正的源码实现要比这个稍微复杂一些,使用的是ThreadLocalMap,但大体都是map的思想,具体参见源码。
[注2]:很多同学都读做Queen(皇后),我内心是崩溃的,正确发音应该是字母Q,读对了在我这里面试都会打高一分。
有热爱Android技术的同学,欢迎加微信公众号 xh18310039919。用诙谐的方式学习Android硬核知识点。