Message的复用

前言

在Android开发中,Message作为Handler通信机制的核心组件之一,其创建方式的选择直接影响着应用的性能表现。传统的新建实例方式(new Message())虽然直观,但在频繁的消息传递场景下可能会引发大量的对象创建与销毁,进而增加垃圾回收的压力和内存分配开销。因此,Android框架为我们提供了一个更加高效的替代方案——通过Message类的静态方法obtain()来获取消息实例。本文将深入解析obtain()方法的工作原理及其背后的设计。

Message.obtain()的精妙之处

Message.obtain()方法巧妙地运用了对象池技术,这是一种旨在减少频繁对象创建与销毁所带来性能损耗的设计模式。下面是对该方法的详细剖析:

线程安全保证

  • 同步控制:方法通过在定义上添加synchronized关键字,确保了在多线程环境下的线程安全性。这意呀着无论多少线程同时尝试调用obtain(),系统都会保证它们按顺序执行,避免了数据竞争和不一致的问题。

对象池的魔法

  • 资源预分配Message.obtain()的核心在于其内部维护的一个消息对象池。这个池预先创建了一定数量的Message对象,并将它们链接在一起。每个Message对象都有一个next字段,形成了一个链表结构,方便管理和复用。

复用逻辑解析

  1. 锁住池访问:通过锁定sPoolSync对象,确保对消息池的操作是原子性的,即任何时刻只有一个线程能够访问池。
  2. 检查与提取:检查池中是否有可用对象。如果有,就从链表头部摘取一个对象(m = sPool),更新池的头部指针,并断开该对象与池的链接。
  3. 重置对象状态:清除摘取对象的next引用和flags标志位,确保对象处于干净、可复用的状态。
  4. 资源计数调整:每当一个对象被复用,池的大小计数器sPoolSize会递减,记录当前池中剩余的可复用对象数量。
  5. 新建对象的最后防线:如果池中无可用对象,则通过常规的new Message()方式创建新对象,确保消息的供应不间断。

资源优化效果

  • 性能提升:通过对象复用,大幅度减少了运行时的内存分配和垃圾回收频率,尤其是在消息处理密集的应用场景下,如UI更新、后台任务调度等,有效提升了应用的运行效率和响应速度。
  • 内存****管理优化:减轻了JVM的管理负担,避免了频繁的内存碎片化问题,对于长时间运行的服务或应用尤为重要。

总结

Message.obtain()不仅是Android开发中一个高效的消息创建策略,更是面向性能优化设计思想的典型体现。它通过简单而高效的对象池模式,最大限度地减少了对象创建的开销。

扩展

享元模式(Flyweight Pattern)是设计模式中的一种,它的核心思想是通过共享技术有效地支持大量细粒度对象的复用。换句话说,享元模式致力于减少创建对象的数量,特别是那些具有相同或相似状态的对象,从而节约内存空间和提高程序效率。它尤其适用于存在大量相似对象的场景,比如文本编辑器中的字符、游戏中的子弹等。

通俗解释

想象一下,你在玩一款射击游戏,游戏中每发射一颗子弹,如果都创建一个新的子弹对象,那么随着游戏的进行,会有成千上万颗子弹对象被创建和销毁,这无疑会消耗大量的内存资源。但事实上,大部分子弹除了位置等少数属性不同外,其他属性如外观、速度等都是相同的。享元模式的做法是,预先创建好几种不同类型的子弹对象(这些是享元对象),游戏运行时,每当需要显示一颗新的子弹时,就从享元池中获取一个已经存在的、类型匹配的子弹对象,仅改变其位置等可变属性,然后使用,这样就大大减少了对象的创建数量。

示例代码

下面是一个简单的享元模式示例,我们以文字处理软件中的字符为例。假设文档中有很多重复的字符,我们不需要为每个字符创建一个新的对象,而是通过享元模式复用字符对象。

// 享元接口
interface Character {
    void display(int pointX, int pointY);
}

// 具体享元角色 - 字符实现类
class ConcreteCharacter implements Character {
    private char character;

    public ConcreteCharacter(char character) {
        this.character = character;
    }

    @Override
    public void display(int pointX, int pointY) {
        System.out.println("在位置 (" + pointX + ", " + pointY + ") 显示字符 '" + character + "'");
    }
}

// 享元工厂类
class CharacterFactory {
    private Map<Character, ConcreteCharacter> pool = new HashMap<>();

    public Character getCharacter(char character) {
        ConcreteCharacter concreteCharacter = pool.get(character);
        if (concreteCharacter == null) {
            concreteCharacter = new ConcreteCharacter(character);
            pool.put(character, concreteCharacter);
        }
        return concreteCharacter;
    }
}

// 客户端代码
public class FlyweightPatternDemo {
    public static void main(String[] args) {
        CharacterFactory factory = new CharacterFactory();

        // 创建并显示字符 'A' 的多个实例
        Character charA1 = factory.getCharacter('A');
        charA1.display(10, 20);

        Character charA2 = factory.getCharacter('A');
        charA2.display(30, 40);

        // 尽管请求了两次'A',但实际只创建了一个'A'的实例
    }
}

在这个例子中,ConcreteCharacter代表具体的享元角色,每个字符都是一个享元对象;CharacterFactory作为享元工厂,负责创建和管理享元对象,确保相同字符的实例只会被创建一次,并通过一个Map来缓存这些实例,实现了对象的复用。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿界新星蔡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值