为何一个线程可以对应一个looper
一:前置知识
- Looper有一个变量:ThreadLocal<Looper>
- Thread.currentThread 打破次元壁,在应用层沟通底层,获得当前线程信息
- 每一个Thread,不管是Android的main thread,还是自己定义的thread,总之就是一个Thread,含有一个ThreadLocalMap变量。
- ThreadLocalMap是一个数组,也就是说,每一个Thread都有一个数组。
二:looper的prepare
looper使用prepare可以创建当前线程的looper,没有prepare就使用handler是会报错的。那prepare是如何保证只为当前线程创造一个looper的呢?我先来分析第一次创建。
下面不会放代码,文字叙述:
- 当调用looper.prepare的时候,会调用自己的变量ThreadLocal<Looper>的set(looper)
- 在ThreadLocal里面,获取当前线程myThread(自己的子线程),
- 然后调用myThread的getMap获取到自己的那个数组(上面提到过),然后把新创建的looper放到数组里面。(使用ThreadLocal<Looper>作索引)
也就是说:
ThreadLocal.set(value) 等价于 当前Thread.table[ThreadLocal.hash()] = value
那么取值呢?
ThreadLocal.get() 等价于 当前Thread.table[ThreadLocal]
直观上理解就是,一个Thread有一个数组,这个数组有很多ThreadLocal对应的值,有苹果的ThreadLocal,也有西瓜的ThreadLocal,也有Looper的ThreadLocal,每一个ThreadLocal实例只能对应一个值。looper在当前Thread里面放上它对应的looper,拿和取都是用对应的ThreadLocal实例作为索引来取,然后Looper里面就是用它那个final ThreadLocal<Looper>变量。所以本质上,因为Looper类中的ThreadLocal<Looper>是一个常量,所以一个thread中只能有一个looper。
三:结尾
ThreadLocal其实用处还是蛮大的,如果想要一个变量,在不同线程里面拥有不同值,可以用这个实现。
比较难理解是因为,ThreadLocal的set和get都用了Thread.currentThread()方法,所以一个threadLocal变量可以获取任意一个thread里面数组的值,有点开挂。倒不如说,开发这个类的人挺聪明的。
2022/5/15更新:
回头来看,其实ThreadLocal就是对Thread类做了一个封装而已,其实自己可以调用Thread t = Thread.currentThread(),然后调用map = t.getMap, map[key] = value来存东西。而ThreadLocal封装之后就只需要ThreadLocal.set和ThreadLocal.get
参考:https://www.kancloud.cn/alex_wsc/android_art/1828635
本文作者:ou尼酱~~~
本文链接:https://www.cnblogs.com/--here--gold--you--want/p/15730088.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步