Android之同一个Thread线程里只能有一个Looper?(ThreadLocal)

目录

  • ThreadLocal 的基本原理
  • Looper 和 ThreadLocal 的结合
    • 如何使用 ThreadLocal 的示例
      • 1. ThreadLocal 变量的定义
      • 2.创建 Looper 实例
      • 3. 获取 Looper 实例
  • 示例
    • 完整的示例
  • 总结

同一个Thread线程里只能有一个Looper对象。
在 Android 中,ThreadLocal 是一个非常有用的工具,它允许你在每个线程中存储和访问独立的变量副本。Looper 是 Android 的消息循环器,它在特定的线程中运行消息循环,并处理消息队列中的消息。ThreadLocal 和 Looper 的结合使得每个线程可以有一个独立的 Looper 实例。

ThreadLocal 的基本原理

ThreadLocal 提供了线程局部变量,确保每个线程都有自己的变量副本,而不会与其他线程的变量副本冲突。它的工作原理如下:

  • 每个线程都有一个 ThreadLocalMap,存储 ThreadLocal 变量。
  • 当线程访问 ThreadLocal 变量时,会从线程的 ThreadLocalMap 中获取对应的值。
  • 如果 ThreadLocal 变量在当前线程中不存在,则会创建一个新的变量副本,并存储在 ThreadLocalMap 中。

Looper 和 ThreadLocal 的结合

在 Android 中,Looper 使用 ThreadLocal 来确保每个线程只能有一个 Looper 实例。

如何使用 ThreadLocal 的示例

1. ThreadLocal 变量的定义

在 Looper 类中,有一个静态的 ThreadLocal 变量,用于存储每个线程的 Looper 实例。

private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

2.创建 Looper 实例

当你在一个线程中调用 Looper.prepare() 方法时,会创建一个新的 Looper 实例,并将其存储在 ThreadLocal 变量中。

public static void prepare() {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper());
}

在这个方法中,首先检查当前线程是否已经有一个 Looper 实例。如果有,则抛出异常,确保每个线程只能有一个 Looper 实例。如果没有,则创建一个新的 Looper 实例,并将其存储在 ThreadLocal 变量中。

3. 获取 Looper 实例

当你需要获取当前线程的 Looper 实例时,可以调用 Looper.myLooper() 方法。

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

这个方法从 ThreadLocal 变量中获取当前线程的 Looper 实例,并返回它。

示例

完整的示例

public class LooperExample {

    public static void main(String[] args) {
        // 创建一个新线程,并在其中创建 Looper
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 准备 Looper
                Looper.prepare();

                // 获取当前线程的 Looper
                Looper looper = Looper.myLooper();
                System.out.println("Looper in thread: " + looper);

                // 开始消息循环
                Looper.loop();
            }
        });

        thread.start();

        // 主线程中尝试获取 Looper
        Looper mainLooper = Looper.myLooper();
        System.out.println("Looper in main thread: " + mainLooper);
    }
}

在示例中,创建了一个新线程,并在其中调用 Looper.prepare() 方法来创建一个 Looper 实例。然后,可以通过 Looper.myLooper() 方法获取当前线程的 Looper 实例。主线程中尝试获取 Looper 时,会返回 null,因为主线程中没有调用 Looper.prepare() 方法。

总结

通过使用 ThreadLocal,Looper 可以确保每个线程只能有一个 Looper 实例。这种机制不仅简化了 Looper 的管理,还确保了消息循环的正确性。每个线程都有自己的消息队列和消息循环,不会与其他线程的消息循环冲突。

Android 之 Handler
HandlerThread 和 Handler 区别
Android之Handler的post方法和sendMessage的区别
Android之Handler是如何保证延迟发送的

你可能感兴趣的:(android,java,handler,ThreadLocal,Looper,线程)