作者:贾东风
转载地址:https://juejin.cn/post/7094241675530207268
阻塞条件
分析MessageQueue的next函数,发生阻塞只会存在以上两种情况
- 队列中消息个数为0,且没有可处理的IdleHandler,此时会一直阻塞
- 队列中消息个数不为0,但是队列头消息还未到执行时间,且没有IdleHandler要执行,此时会阻塞时间n,n表示队列头消息距离执行的时间
以上两种阻塞情况,mBlock都为true.只有这两种情况需要唤醒。
一言以蔽之,没有IdleHandle要执行,且队列中没有立即要可执行的消息时,会阻塞
唤醒条件
唤醒条件:
-
队列为空,或者队列头消息还未到执行时间,且当前消息待执行时间小于队列头消息,此时才需要唤醒。一言以蔽之,也就是当前消息插入到队列头部时,才需要唤醒。
-
mBlocked为true,也就是没有Idle消息要处理,且当前队列头消息时同步屏障消息,且当前消息时异步消息,此时需要立即处理,因为该异步消息对响应及时性要求比较高。
boolean enqueueMessage(Message msg, long when) {
...
synchronized (this) {
...
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;
}
网友评论