直播平台源码,信息的双端同步处理
直播平台源码,信息的双端同步处理
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>} |
以上就是直播平台源码,信息的双端同步处理, 更多内容欢迎关注之后的文章
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现