直播平台源码,信息的双端同步处理

直播平台源码,信息的双端同步处理

Handler组件中包含:Looper、Message、MessageQueue、Handler。

在Message中,有一个变量flag,用于标记这个Message正在被使用、此消息是异步消息等,通过一个方法isAsynchronous()可以获取当前Message是否为异步消息。同时,在Message中有一个变量target,是Handler类型的,表示最终由这个Handler进行处理。

平时我们发送消息时,这个target是不可以为null的。

 

1
//MessageQueue.java<br>boolean enqueueMessage(Message msg, long when) {<br>    if (msg.target == null) {<br>        throw new IllegalArgumentException("Message must have a target.");<br>    }<br>    if (msg.isInUse()) {<br>        throw new IllegalStateException(msg + " This message is already in use.");<br>    }<br>}

但是在发送屏障消息的时候,target是可以为空的,它本身仅仅是起屏蔽普通消息的作用,所以不需要target。MessageQueue中提供了postSyncBarrier()方法用于插入屏障消息。

 

1
//MessageQueue.java<br>/**<br> * @hide<br> */<br>public int postSyncBarrier() {<br>    return postSyncBarrier(SystemClock.uptimeMillis());<br>}<br>private int postSyncBarrier(long when) {<br>    synchronized (this) {<br>        //这个token在移除屏障时会使用到<br>        final int token = mNextBarrierToken++;<br>        final Message msg = Message.obtain();<br>        msg.markInUse();<br>        msg.when = when;<br>        msg.arg1 = token;<br>        <br>        //在屏障的时间到来之前的普通消息,不会被屏蔽<br>        Message prev = null;<br>        Message p = mMessages;<br>        if (when != 0) {<br>            while (p != null && p.when <= when) {<br>                prev = p;<br>                p = p.next;<br>            }<br>        }<br>        <br>         //插入到单链表中<br>        if (prev != null) { // invariant: p == prev.next<br>            msg.next = p;<br>            prev.next = msg;<br>        } else {<br>            msg.next = p;<br>            mMessages = msg;<br>        }<br>        return token;<br>    }<br>}

 

看起来比较简单,可以获取的信息如下:

 

屏障消息和普通消息区别在于屏幕没有target,普通消息有target是因为它需要将消息分发给对应的target,而屏幕不需要被分发,它就是用来挡住普通消息来保证异步消息优先处理的

屏障和普通消息一样可以根据时间来插入到消息队列中的适当位置,并且只会挡住它后面的同步消息的分发

postSyncBarrier会返回一个token,利用这个token可以撤销屏障

postSyncBarrier是hide的,使用它得用反射

插入普通消息会唤醒消息对了,但插入屏障不会

现在屏障已经插入到消息队列中了,它是如何挡住普通消息而只需要异步消息进行执行的呢?Looper是通过MessageQueue的next方法来获取消息的,来看看

 

1
//MessageQueue.java<br>Message next() {<br>    ...<br>    int pendingIdleHandlerCount = -1;<br>    int nextPollTimeoutMillis = 0;<br>    for (;;) {<br>        //如有消息被插入到消息队列或者超时时间到,就被唤醒,否则会阻塞在这里<br>        nativePollOnce(ptr, nextPollTimeoutMillis);<br>        synchronized (this) {<br>            final long now = SystemClock.uptimeMillis();<br>            Message prevMsg = null;<br>            Message msg = mMessages;<br>            //遇到屏障  它的target是空的<br>            if (msg != null && msg.target == null) {<br>                //找出屏障后面的异步消息,<br>                do {<br>                    prevMsg = msg;<br>                    msg = msg.next;<br>                    //isAsynchronous()返回true才是异步消息<br>                } while (msg != null && !msg.isAsynchronous());<br>            }<br>            <br>            //如果找到了异步消息<br>            if (msg != null) {<br>                if (now < msg.when) {<br>                    //还没到处理时间,再等一会儿<br>                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);<br>                } else {<br>                    //到处理时间了,就从链表中移除,返回这个消息<br>                    mBlocked = false;<br>                    if (prevMsg != null) {<br>                        prevMsg.next = msg.next;<br>                    } else {<br>                        mMessages = msg.next;<br>                    }<br>                    msg.next = null;<br>                    msg.markInUse();<br>                    return msg;<br>                }<br>            } else {<br>                //如果没有异步消息就一直休眠,等待被唤醒<br>                nextPollTimeoutMillis = -1;<br>            }<br>            ...<br>        }<br>        ...<br>    }<br>}

 

以上就是直播平台源码,信息的双端同步处理, 更多内容欢迎关注之后的文章

 

posted @   云豹科技-苏凌霄  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示