当前位置: 首页 > article >正文

Android Handler同步屏障:深入解析

Android Handler同步屏障:深入解析

在Android开发中,HandlerMessageQueue是处理线程间通信的重要组件。除了常见的消息发送和处理功能,Handler还提供了一个高级特性:同步屏障。本文将深入探讨这一特性,包括它的工作原理、应用场景,并提供实际的代码示例。

同步屏障机制简介

同步屏障是MessageQueue中的一种特殊机制,用于临时阻塞消息队列中的消息处理。当设置同步屏障时,它会阻止所有普通消息的处理,同时允许立即消息(例如带回调的消息或Runnable对象)继续执行。

工作原理

设置同步屏障

同步屏障通过在MessageQueue中插入一个特殊的、没有目标Handler的消息来实现。这个屏障阻止了所有后续的普通消息处理。

处理立即消息

尽管存在同步屏障,但某些类型的消息(如带有回调的消息或Runnable)仍然可以被执行。这些消息通常不受时间戳的约束,因此可以越过屏障处理。

移除同步屏障

当同步屏障被移除后,之前被阻塞的普通消息将恢复处理。

应用场景

同步屏障在以下情况下非常有用:

  • 确保立即任务优先处理:在需要优先执行某些紧急任务时,可以使用同步屏障暂时阻止其他消息的处理。
  • 避免死锁和资源竞争:在复杂的消息交互场景中,使用同步屏障可以防止因消息处理顺序不当引发的死锁或资源竞争。

代码示例

假设我们有一个Handler,我们想要在处理一些紧急任务前暂时阻止其处理其他消息:

// 创建Handler和MessageQueue
Handler handler = new Handler(Looper.getMainLooper());

// 设置同步屏障
MessageQueue queue = Looper.getMainLooper().getQueue();
Field field = MessageQueue.class.getDeclaredField("mMessages");
field.setAccessible(true);
Message barrier = Message.obtain();
barrier.what = MessageQueue.MSG_SYN_BARRIER;
queue.enqueueMessage(barrier, System.currentTimeMillis());

// 添加一个立即执行的任务
handler.post(() -> {
    // 紧急任务代码
});

// 移除同步屏障
handler.postDelayed(() -> {
    field.set(queue, barrier.next);
    barrier.recycle();
}, 1000);

注意事项

使用同步屏障时需谨慎,因为不恰当的使用可能会导致消息处理的延迟或阻塞,影响应用性能和响应能力。

总结

Handler的同步屏障是Android中一个强大但不太为人知的特性,它可以用于控制消息队列中的消息处理顺序。正确使用同步屏障可以在复杂的消息处理场景中带来显著的好处,但需要确保恰当使用以避免潜在的问题。通过本文的讲解和代码示例,希望能帮助你更好地理解和应用这一高级特性。

当Vsync信号到来时,会往主线程的MessageQueue中插入一条异步消息,由于在scheduleTraversals中给MessageQueue中插入了同步屏障消息,那么当执行到同步屏障时,会取出异步消息执行。

屏障消息和普通消息的区别是屏障消息没有target属性,普通消息有target属性是因为要将消息分发给target指向的handler处理
屏障消息会插入到MessageQueue中合适的位置,这个消息以后的普通消息将被屏蔽
postSyncBarrier返回一个int类型的数值,通过这个数值可以撤销屏障
postSyncBarrier方法是私有的,如果我们想调用它就得使用反射
插入普通消息会唤醒消息队列,但是插入屏障不会

源码处理过程中会先判断此消息是否为屏障消息,如果是屏障消息,则去循环遍历,直到寻找到异步消息为止。通过这种方式跳过了普通消息,直接执行异步消息。也就是说同步屏障为handler消息机制提供了一种优先级策略,异步消息的优先级要高于同步消息。

另外需要注意的是:同步屏障不会自动移除,使用完成之后需要手动移除,不然会造成同步消息无法处理。也可以通过removeSyncBarrier(int token)方法进行移除,token就是之前添加屏障时返回的token。

对于绘制流程中,为什么要发送一个同步屏障并且发送异步消息,应该心中也有了答案,不错,就是为了让保证在vsync信号到来时,异步任务可以优先执行,从而绘制任务可以被及时执行,避免造成界面卡顿。


http://www.kler.cn/a/147660.html

相关文章:

  • 时钟之CSS+JS版
  • 使用--log-file保存pytest的运行日志
  • 深度学习的多主机多GPU协同训练
  • 【postman】怎么通过curl看请求报什么错
  • STM32学习笔记-----UART的概念
  • 微信小程序——01开发前的准备和开发工具
  • C语言—指针初始化
  • js手写面试题【附带注释】
  • Python 安装Vue依赖包发生异常:npm ERR! notsup Required: {“node“:“^18.17.0 || >=20.5.0“}
  • Java中的jvm——面试题+答案(Java虚拟机的基本概念,包括内存区域、类加载机制、垃圾回收等)——第15期
  • 规划类3d全景线上云展馆帮助企业轻松拓展海外市场
  • SpringBoot——拦截器
  • MySQL数据库如何实现跨服务器访问数据
  • 基于SSM实现的叮当书城
  • UE4/UE5 雾
  • ElementUI table+dialog实现一个简单的可编辑的表格
  • Vue3 + Scss 实现主题切换效果
  • 2023年APMCM亚太杯数学建模竞赛C题思路解析
  • python 如何调用GPT系列的api接口,实现想要的功能
  • Jenkins 整合 Docker 自动化部署
  • 【Java学习笔记】72 - 满汉楼 - 餐饮管理系统
  • Vatee万腾的数字化创新航程:Vatee科技力量的前瞻之光
  • Python爬虫之代理IP与访问控制
  • 万字解析设计模式之模板方法与解释器模式
  • MySQL基础篇一
  • 【蓝桥杯备考】第十二届蓝桥杯省赛Java B组真题 编程题