参考资料:
ThreadLocal:https://www.cnblogs.com/coshaho/p/5127135.html
Handler:https://www.jianshu.com/p/3d8f7ec1017a
0.ThreadLocal和Thread的关系
每个Thread中都有一个存储ThreadLocal的Map对象,这个Map不是使用的集合类中的Map,用的是一个叫做“ThreadLocalMap”(从名字可以明显看出来它的作用了)的类来存储。ThreadLocalMap是一个可以存储key-value的map,key就是ThreadLocal,value就是要存储的跟ThreadLocal对应的值。
这里的ThreadLocalMap是ThreadLocal的“基友类”。
下图看下两者关系
1.线程绑定
问起Handler的原理,会提起Looper和MessageQueue跟线程绑定,balabala。
这里实现线程绑定就是使用的Thread中的ThreadLocalMap来实现。
如何使用ThreadLocal呢。首先需要一个Manager类来持有一个ThreadLocal<T>的实例。不同的Thread将这个实例和想存储的值保存起来就好咯。ThreadLocal提供了set、get等等方法来方便获取或者保存当前运行线程(Thread.currentThread()可以获取当前线程)对应的存储值。这样为了不同的功能,我们可以定义不同的ThreadLocal,而且互不干扰。
线程绑定,直接写成Map<Thread, value>不就可以实现吗,为什么要写得如此复杂。
这种存储结构的好处:
1、线程死去的时候,线程共享变量ThreadLocalMap则销毁。
2、ThreadLocalMap<ThreadLocal,Object>键值对数量为ThreadLocal的数量,一般来说ThreadLocal数量很少,相比在ThreadLocal中用Map<Thread, Object>键值对存储线程共享变量(Thread数量一般来说比ThreadLocal数量多),性能提高很多。
2.Handler
Hander有一个相关类为Looper,这个就是上面所说的Manager类。
Looper有几个属性值:
// 存储Looper的ThreadLocal,可以看出Looper不仅充当Manager,还作为基础数据类(存储MessageQueue等信息)
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
// 主线程的Looper
private static Looper sMainLooper;
// Looper对应的MessageQueue
final MessageQueue mQueue;
可以看出Looper不仅充当Manager,还作为基础数据类(存储MessageQueue等信息),通过sThreadLocal,实现了线程和Looper的绑定。
Looper有个重要方法:
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
由此,大部分Looper的代码基本上可以知道是什么意思了。