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

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

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

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

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

 

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

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

 

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

 

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

 

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

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

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

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

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

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

 

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

 

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

 

posted @ 2022-05-06 14:38  云豹科技-苏凌霄  阅读(44)  评论(0)    收藏  举报