zoukankan      html  css  js  c++  java
  • 一个例子了解 HandlerThread,Looper,ThreadLocal,Handler,MessageQueue,Message的关系

    我们经常会用到 HandlerThread 在线程中执行Runnable方法,调用代码如下,

    private HandlerThread mHandlerThread = new HandlerThread("MainActivity");
    mHandlerThread.start();
    mWorkHandler = new Handler(mHandlerThread.getLooper());
    mWorkHandler.post(new Runnable() {
      @Override
      public void run() {

      }
    });
    相关机制是怎么触发的呢?
    这里面涉及到HandlerThread,Looper,ThreadLocal,Handler,MessageQueue,Message 等概念,流程如下:

    1.mHandlerThread.start();
    本身继承Thread,该方法启动线程,
    HandlerThread run方法
    HandlerThread.run相关代码如下:
    public void run() {
      mTid = Process.myTid();
      Looper.prepare();
      synchronized (this) {
      mLooper = Looper.myLooper();
      notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
    }

    1.1 执行 Looper.prepare()
      Looper.prepare() 创建Looper实例放在 sThreadLocal 对象里面, 调用如下:
      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));
      }
    1.2 Looper.myLooper()方法从 sThreadLocal 中获取Looper实例(这个实例是线程独立的,即获取的是对应线程创建的Looper实例)
      给 HandlerThread 的全局变量 mLooper

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

    1.3 执行Looper.loop()创建消息循环,
      核心逻辑是从 当前线程的Looper中取出 MessageQueue,循环遍历 MessageQueue 中的消息
      Looper.loop()代码
      public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
        ...
      }

    2.new Handler(mHandlerThread.getLooper())
      2.1 mHandlerThread.getLooper() 获取HandlerThread 中创建的 Looper对象
      2.2 把获取的Looper初始化到Hander中
    3. mWorkHandler.post(new Runnable()..)
      3.1通过 getPostMessage 方法将Runnable封装到 Message 对象中
      3.2 最终会调用sendMessageAtTime方法
      该方法中MessageQueue对象 mQueue 就是从2.1 Hander中Lopper中获取的,而且这个MessageQueue 在1.3 消息循环中不停的被遍历,
      你只要向 MessageQueue 中添加Runnable封装 Message,就会在指定的时间执行 Runnable方法。
     

    Handler.java 相关调用代码如下:
      public final boolean post(Runnable r)
      {
        return sendMessageDelayed(getPostMessage(r), 0);
      }

      private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
       return m;
     }

      public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
          RuntimeException e = new RuntimeException(
          this + " sendMessageAtTime() called with no mQueue");
          Log.w("Looper", e.getMessage(), e);
          return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
      }

  • 相关阅读:
    Makefile 常用函数表
    情绪管理
    网赚呓语
    Gym 100952C&&2015 HIAST Collegiate Programming Contest C. Palindrome Again !!【字符串,模拟】
    Gym 100952B&&2015 HIAST Collegiate Programming Contest B. New Job【模拟】
    Gym 100952A&&2015 HIAST Collegiate Programming Contest A. Who is the winner?【字符串,暴力】
    HDU 1024 Max Sum Plus Plus【动态规划求最大M子段和详解 】
    HDU 1003 Max Sum【动态规划求最大子序列和详解 】
    HDU 1010 Tempter of the Bone【DFS经典题+奇偶剪枝详解】
    DFS中的奇偶剪枝学习笔记
  • 原文地址:https://www.cnblogs.com/adamli/p/13408190.html
Copyright © 2011-2022 走看看