通过Java的ThreadLocal来了解Handler的线程绑定

参考资料:

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数量多),性能提高很多。

摘自:https://www.cnblogs.com/coshaho/p/5127135.html

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的代码基本上可以知道是什么意思了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章