为何一个线程可以对应一个looper

一:前置知识

  • Looper有一个变量:ThreadLocal<Looper>
  • Thread.currentThread 打破次元壁,在应用层沟通底层,获得当前线程信息
  • 每一个Thread,不管是Android的main thread,还是自己定义的thread,总之就是一个Thread,含有一个ThreadLocalMap变量。
  • ThreadLocalMap是一个数组,也就是说,每一个Thread都有一个数组。

 

二:looper的prepare

looper使用prepare可以创建当前线程的looper,没有prepare就使用handler是会报错的。那prepare是如何保证只为当前线程创造一个looper的呢?我先来分析第一次创建。

下面不会放代码,文字叙述:

  1. 当调用looper.prepare的时候,会调用自己的变量ThreadLocal<Looper>的set(looper)
  2. 在ThreadLocal里面,获取当前线程myThread(自己的子线程),
  3. 然后调用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>变量。

 

三:结尾

ThreadLocal其实用处还是蛮大的,如果想要一个变量,在不同线程里面拥有不同值,可以用这个实现。

比较难理解是因为,ThreadLocal的set和get都用了Thread.currentThread()方法,所以一个threadLocal变量可以获取任意一个thread里面数组的值,有点开挂。倒不如说,开发这个类的人挺聪明的。

 

 

 

参考:https://www.kancloud.cn/alex_wsc/android_art/1828635

上一篇:hive元数据管理与存储


下一篇:Hive metastore三种配置方式