【Android】Handler 线程问题

本文讲解一个线程有几个 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 。

如果本文对你有帮助,请点赞支持!!!

猜你喜欢

转载自blog.csdn.net/cnwutianhao/article/details/107646259
今日推荐