本文讲解一个线程有几个 Handler ?一个线程有几个 Looper ?该如何保证?
一、一个线程有几个 Handler ?
答:一个线程有多个 Handler 。
原因:在一个 Activity 里 new 一个 Handler ,在另一个 Activity 里又 new 了一个 Handler 。只要内存够用想 new 多少个 Handler 都可以。
二、一个线程有几个 Looper ?该如何保证?
答:一个线程有一个 Looper 。
解:
关键字:ThreadLocal。实际上 ThreadLocal 就是一个 Key Value 键值对。
先看源码对 Looper 是怎样进行初始化的
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper 的构造函数是一个私有的构造函数。也就意味着不可能在其他类里进行初始化。
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
内部定义了一个 prepare 函数来进行初始化。在 ThreadLocal.set() 的时候进行初始化。
Q:初始化的 Looper 是如何和线程进行绑定的?
A:得看 ThreadLocal.set() 的过程
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) map.set(this, value);
else createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
set 函数传入的 value 就是 Looper ,set 函数第一行用来获取当前线程。第二行根据当前线程来获取对应的 ThreadLocalMap 。
根据前两行代码可知一个线程对应一个 Map 。
map.set() 函数源码:
private void set(ThreadLocal < ?>key, Object value) {
Entry[] tab = table;
...
tab[i] = new Entry(key, value);
...
}
ThreadLocal 本身作为 Key ,Looper 作为 Value。并且是一一对应。
所以在 prepare 的时候,一个 ThreadLocal 对应了一个 Looper 。而且这个 ThreadLocal 是跟线程进行绑定的。
那么就会有一个疑问 Looper 里面存在多个 ThreadLocal 那不就完蛋了吗?
查看 Looper 源码
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
发现 ThreadLocal 是 final ,所以他只能有一个。
那就会有一个疑问 Key 可以不变,Value 可以有多个,那程序不就乱套了吗?
查看 prepare 函数源码
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
每当执行 prepare 的时候,会根据唯一的 ThreadLocal 来 get 一下。如果发现 ThreadLocal 已经有值了那就会发一个 Exception 。也就彻底保证了唯一性。
综上所述:一个线程(Thread)对应一个 Map(ThreadLocalMap),一个 Map 里面会有多个 Entry ,但是 Entry 里面会有一个键(ThreadLocal)对应一个值(Looper)。也就是说一个线程有一个 Looper 。
如果本文对你有帮助,请点赞支持!!!