码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • MessageQueue和Looper学习


    MessageQueue和Looper的设计很巧妙,但是代码看上去很繁琐,我们不必了解其实现细节,知道其思路即可,这里我们探讨其基本原理,

    调用Handler的post等方法后,会调用到MessageQueue的enqueueMessage来按照执行时间顺序来排列,最好理解的取队列数据的实现方案是,while执行循环,不断的取队列头部的数据,但显然不能这样做。

    而Looper中使用epoll_wait来进行阻塞,在队列头部放入数据后,进行wake操作,通知Looper可以检查了,于是epoll_wait退出阻塞,判断队列头部数据的时间是否<=当前时间,符合的活,取出来,执行里面的操作处理。然后对新的队列头部数据进行同样的操作。

    不符合,计算时间差,作为继续要等待的时间,传给epoll_wait,等到了时间,自动解除阻塞,进行下一步判断处理。

    在处理的时候,只需要关注队列头部的数据的唤醒时间。

    就是这样清楚。

    关键就在于,epoll_wait可以1进行阻塞,2收到信号实时解除阻塞,3到达设定时间后解除阻塞

    int epoll_wait(int epfd,struct epoll_event * events, int maxevents,int timeout);

    boolean enqueueMessage(Message msg, long when) {

            if (msg.target == null) {

                throw new IllegalArgumentException("Message must have a target.");

            }

            synchronized (this) {

                if (msg.isInUse()) {

                    throw new IllegalStateException(msg + " This message is already in use.");

                }

                if (mQuitting) {

                    IllegalStateException e = new IllegalStateException(

                            msg.target + " sending message to a Handler on a dead thread");

                    Log.w(TAG, e.getMessage(), e);

                    msg.recycle();

                    return false;

                }

                msg.markInUse();

                msg.when = when;

                Message p = mMessages;

                boolean needWake;

                if (p == null || when == 0 || when < p.when) {

                    // New head, wake up the event queue if blocked.

                    msg.next = p;

                    mMessages = msg;

                    needWake = mBlocked;

                } else {

                    // Inserted within the middle of the queue.  Usually we don't have to wake

                    // up the event queue unless there is a barrier at the head of the queue

                    // and the message is the earliest asynchronous message in the queue.

                    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;

                        }

                    }

                    msg.next = p; // invariant: p == prev.next

                    prev.next = msg;

                }

                // We can assume mPtr != 0 because mQuitting is false.

                if (needWake) {

                    nativeWake(mPtr);

                }

            }

            return true;

    }

    Looper.java

    137    public static void loop() {

    138        final Looper me = myLooper();

    139        if (me == null) {

    140            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

    141        }

    142        final MessageQueue queue = me.mQueue;

    143

    144        // Make sure the identity of this thread is that of the local process,

    145        // and keep track of what that identity token actually is.

    146        Binder.clearCallingIdentity();

    147        final long ident = Binder.clearCallingIdentity();

    148

    149        // Allow overriding a threshold with a system prop. e.g.

    150        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'

    151        final int thresholdOverride =

    152                SystemProperties.getInt("log.looper."

    153                        + Process.myUid() + "."

    154                        + Thread.currentThread().getName()

    155                        + ".slow", 0);

    156

    157        boolean slowDeliveryDetected = false;

    158

    159        for (;;) {

    160            Message msg = queue.next(); // might block

    161            if (msg == null) {

    162                // No message indicates that the message queue is quitting.

    163                return;

    164            }

    165

    166            // This must be in a local variable, in case a UI event sets the logger

    167            final Printer logging = me.mLogging;

    168            if (logging != null) {

    169                logging.println(">>>>> Dispatching to " + msg.target + " " +

    170                        msg.callback + ": " + msg.what);

    171            }

    172

    173            final long traceTag = me.mTraceTag;

    174            long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

    175            long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;

    176            if (thresholdOverride > 0) {

    177                slowDispatchThresholdMs = thresholdOverride;

    178                slowDeliveryThresholdMs = thresholdOverride;

    179            }

    180            final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);

    181            final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

    182

    183            final boolean needStartTime = logSlowDelivery || logSlowDispatch;

    184            final boolean needEndTime = logSlowDispatch;

    185

    186            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {

    187                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));

    188            }

    189

    190            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;

    191            final long dispatchEnd;

    192            try {

    193                msg.target.dispatchMessage(msg);

    194                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;

    195            } finally {

    196                if (traceTag != 0) {

    197                    Trace.traceEnd(traceTag);

    198                }

    199            }

  • 相关阅读:
    不可变集合的详细概述
    二次封装这几个 element-ui 组件后,让代码更加优雅了
    宠物之家网站大学生网页制作教程 学生HTML静态宠物网页设计作业成品 DIV布局简单动物网页制作代码
    vue3 setup语法糖
    ALP300智能型低压马达保护器
    Python+ Flask轻松实现Mock Server
    GBase 8c V3.0.0数据类型——文本检索函数
    npm 与 yarn 命令比较
    C语言结构体的初始化方式
    WaveletPool:抗混叠在微小目标检测中的重要性
  • 原文地址:https://blog.csdn.net/aaajj/article/details/127590954
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号