前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【数据结构】线性表 ③ ( 链表示例 | Android MessageQueue 源码分析 | enqueueMessage 添加消息 | next 取出消息 )

【数据结构】线性表 ③ ( 链表示例 | Android MessageQueue 源码分析 | enqueueMessage 添加消息 | next 取出消息 )

作者头像
韩曙亮
发布2023-10-11 16:50:34
1490
发布2023-10-11 16:50:34
举报
文章被收录于专栏:韩曙亮的移动开发专栏

一、Android MessageQueue 源码分析

在 Android 系统中的 Handler 机制 中 , 涉及到了 Handler , Message , Looper , MessageQueue 等组件 , 其中 MessageQueue 是消息队列 , 其中包含了很多 单链表 元素 ;

MessageQueue 源码地址 : https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/os/MessageQueue.java

Message 源码地址 : https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/os/Message.java

1、Message 消息

在 Message 消息的源码中 , 包含了 Message next 指针 , 指向单链表中的下一个 Message 节点 ;

代码语言:javascript
复制
    // sometimes we store linked lists of these things
    /*package*/ Message next;

参考源码 : android/os/Message.java#115

2、MessageQueue 消息队列 enqueueMessage 添加消息

在 MessageQueue 消息队列 中的 boolean enqueueMessage(Message msg, long when) 函数 是 向 消息队列 中添加 Message 消息的方法 ;

该函数的作用是 在 long when 时间后 , 执行 Message msg 消息 ;

添加 Message msg 消息时 , 需要参考 long when 时间参数 , 时间越长 Message 排序越靠后 , 时间越短 Message 的位置越靠前 ;

MessageQueue 消息队列 , 是 按照执行时间进行排序的 ;

在下面的代码逻辑中 , 一直进行死循环 , 判断当前的 Message 节点指针 p 指向的节点 , 如果该节点的时间小于传入的 long when 时间参数 , 那么找到了该节点 , 循环结束 , 插入节点 ;

插入节点的操作 , 只需要两行代码 , 改变指针的指向即可 , msg.next = p; prev.next = msg;

该 MessageQueue 几乎不需要查询遍历 , 但是会 频繁进行插入操作 , 因此在该场景下 , 使用单链表是最佳选择 ;

大部分情况下 , Handler 发送 Message 都会将 Message 消息插入到 Looper 中的 MessageQueue 的最前面 , 如果要使用顺序表 , 则每次插入 , 都需要挪动整个顺序表中的元素 ;

代码语言:javascript
复制
                // 插入到队列的中间。通常我们不需要唤醒事件队列,
                // 除非在队列的头部有一个障碍,并且该消息是队列中最早的异步消息。
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                // 插入 Message 节点
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;

参考源码 : android/os/MessageQueue.java#564

3、MessageQueue 消息队列 next 取出消息

在 MessageQueue 消息队列 中的 Message next() 函数 , 就是从 MessageQueue 消息队列中取出消息 , 并处理消息的函数 ;

Message next 函数位置 : android/os/MessageQueue.java#326

直接调用 msg = msg.next; 获取下一条消息 , 获取消息后 , 判定该消息的执行时间是否到了 , now < msg.when , 如果时间到了 , 就执行该消息 , 如果时间没有到 , 则设置超时唤醒 ;

代码语言:javascript
复制
                // 尝试检索下一条消息。如果找到,返回。
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // 被障碍物阻挡的。查找队列中的下一个异步消息。
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // 下一条消息尚未准备好。设置一个超时唤醒当它准备好了。
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // 没有更多的信息。
                    nextPollTimeoutMillis = -1;
                }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Android MessageQueue 源码分析
    • 1、Message 消息
      • 2、MessageQueue 消息队列 enqueueMessage 添加消息
        • 3、MessageQueue 消息队列 next 取出消息
        相关产品与服务
        消息队列
        腾讯云消息队列 TDMQ 是分布式架构中的重要组件,提供异步通信的基础能力,通过应用解耦降低系统复杂度,提升系统可用性和可扩展性。TDMQ 产品系列提供丰富的产品形态,包含 CKafka、RocketMQ、RabbitMQ、Pulsar、CMQ 五大产品,覆盖在线和离线场景,满足金融、互联网、教育、物流、能源等不同行业和场景的需求。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档