Handler同步屏障是一种特殊的机制,用于在消息队列中临时阻塞同步消息(普通消息)的处理,同时允许异步消息继续执行。
一、定义与工作原理
同步屏障通过在MessageQueue中插入一个特殊的、没有目标Handler的消息(即target属性为null的消息)来实现。
这个屏障会阻止所有后续的同步消息被处理,直到屏障被移除。
二、应用场景
-
确保立即任务优先处理:
- 在需要优先执行某些紧急任务时,可以使用同步屏障暂时阻止其他消息的处理。
- 例如,在绘制界面时,可能需要优先处理绘制消息以避免卡顿。
-
避免死锁和资源竞争:
- 在复杂的消息交互场景中,使用同步屏障可以防止因消息处理顺序不当引发的死锁或资源竞争。
四、识别同步消息和异步消息
在Android的MessageQueue中,消息(Message)分为同步消息(普通消息)和异步消息。这两种消息主要通过Message对象的isAsynchronous标志来区分:
- 同步消息(普通消息):默认情况下,通过Handler发送的消息都是同步消息,即
isAsynchronous标志为false。这些消息按照它们在消息队列中的顺序和时间戳进行处理。 - 异步消息:异步消息是通过设置
isAsynchronous标志为true来标识的。这类消息在消息队列中具有更高的优先级,可以越过同步屏障被优先处理。
五、设置同步屏障
同步屏障通过在MessageQueue中插入一个特殊的、没有目标Handler的消息(即target属性为null的消息)来实现。
这个屏障会阻止所有后续的同步消息被处理,直到屏障被移除。
1. 插入同步屏障
同步屏障的插入通常是通过MessageQueue的postSyncBarrier方法实现的,
但需要注意的是,这个方法在Android的SDK中是隐藏的(即标记为@hide),因此无法直接调用。
然而,可以通过反射或其他方式间接调用。
// 假设queue是已经获取的MessageQueue实例
// 注意:postSyncBarrier方法是私有的,这里仅为示例,实际使用中可能需要通过反射调用
int token = queue.postSyncBarrier(SystemClock.uptimeMillis());
postSyncBarrier方法会返回一个token,这个token在后续移除屏障时需要用到。
2. 消息队列处理逻辑
当MessageQueue在处理消息时,如果遇到target为null的消息(即同步屏障),
它会跳过所有后续的同步消息,直到找到一条异步消息或消息队列为空。
这个过程是通过MessageQueue的next方法实现的。
// MessageQueue的next方法大致逻辑(简化版)
Message next() {
// ...
for (;;) {
// ...
synchronized (this) {
// ...
if (msg != null && msg.target == null) {
// 同步屏障,找到下一个异步消息
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
// ...
}
// ...
}
}
六、移除同步屏障
同步屏障不会自动移除,因此在使用完毕后需要手动移除,否则会导致同步消息无法被处理。
移除屏障可以通过MessageQueue的removeSyncBarrier方法实现,并传入之前插入屏障时返回的token。
// 假设token是之前插入屏障时返回的token
queue.removeSyncBarrier(token);
七、总结
1、同步屏障,就是给MessageQueue发送一个target为null的消息(即同步屏障)
2、默认情况下Handler发送的都是同步消息,异步消息指isAsynchronous标志为true
3、同步屏障要手动移除