为何一个线程可以对应一个looper
2022-01-05 10:01
417 查看
一:前置知识
- 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里面数组的值,有点开挂。倒不如说,开发这个类的人挺聪明的。
参考:https://www.kancloud.cn/alex_wsc/android_art/1828635
相关文章推荐
- java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
- java 中有几种方法可以实现一个线程? 用什么关键字修 饰同步方法? stop()和 suspend()方法为何不推荐使用?
- java开发线程篇1:java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
- 【Java面试题】23 java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
- java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
- java基础问题---java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用
- java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用
- Android Handler机制 (一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理 ,但是 每个线程中最多只有一个Looper,肯定也就一个MessageQuque)
- java中有几种方法可以实现一个线程?用什么关键字修饰同步方法 stop()和suspend()方法为何不推荐使用?
- java中有几种方法可以实现一个线程用什么关键字修饰同步方法 stop()和suspend()方法为何不推荐使用
- 编写一个程序,可以一直接收键盘字符, 如果是小写字符就输出对应的大写字符, 如果接收的是大写字符,就输出对应的小写字符, 如果是数字不输出。
- 实现一个函数int my_atoi(char s[]),可以将一个字符串转换为对应的整数。
- 一个域名最多能对应几个IP地址?,一个IP地址可以绑定几个域名?
- android Toast为何必须在主线程或者初始化了Looper的线程中执行show操作
- 编写一个程序,可以一直接收键盘字符, 如果是小写字符就输出对应的大写字符, 如果接收的是大写字符,就输出对应的小写字符, 如果是数字不输出。
- 编写一个程序,可以一直接收键盘字符,如果是小写字符就输出对应的大写字符,如果接收的是大写字符,就输出对应的小写字符,如果是数字不输出。
- 【C语言】【笔试题】实现一个函数int my_atoi(char s[]),可以将一个字符串转换为对应的整数。
- 编写一个程序,可以一直接收键盘字符,如果是小写字符就输出对应的大写字符,如果是大写字符,就输出对应的小写字符,如果是数字不输出
- 面试官:来,手写一个线程安全并且可以设置过期时间的LRU缓存
- 交换机的一个端口可以对应多个MAC吗?