android内存优化-对象池模式和享元模式

Android 对象池的简单实现 Android 对象池的简单实现 首先简单说一下为什么要使用对象池,使用对象池的主要原因是防止短时间内频繁大量的创建和销毁对象,也就是频繁GC,引起内存抖动,导致影响我们应用的性能。 package com.qumitech.common.pool /** * author : hnliu * e-mail : 1017928908@qq.com * create date : 2020/09/12 * description :管理对象池的接口 */ in 阅读详情

在内存优化的道路中,往往会遇到对大量使用对象的情况,为了减少内存的分配,减少垃圾回收器调用次数,合理的使用对象设计模式去设计对象,减少内存抖动的风险。对于对象的重用,主要有2中设计模式:对象池模式和享元模式

对象池模式
思想:为避免一个可能会被重用的对象,被垃圾回收。从而节省了创建对象所花费的时间和内存的重新分配。使用一个对象池的对象(万物皆对象)去负责管理大量可重用的对象,是重用的对象被请求在再次使用。
角色
  • ReusableObject 可重用对象 被客户端使用,被对象池管理
  • Client 客户端 请求者,需要使用对象干事情,向对象池获取可用的对象
  • ObjectPool 对象池 持有可重用对象,负责管理对象:创建 分配 回收
注意点
  • 对象池所包含的对象会有上限(必然的,无上限,就是无限创建,那对内存无任何帮助)
  • 如果客户端请求ReusableObject时,对象池已满,所以对象正在被使用中。那么请求会被延迟,知道其他客户端归还可重用对象。
  • 当刚被用完的对象,在传递给下一个客户端使用前,需要恢复到一个默认的状态,不能让可能收到一个不可预期的对象,同时也方便管理这些对象。
  • 该模式在多线程环境中使用,需要处理线程安全,避免并发修改对象池中对象的情况

对象池流程图

举个例子

客人在餐厅里吃饭,需要找个桌子。如果人很多,桌子不够用了,就需要等待。同时如果客人吃完饭,就需要服务员来清理桌子,让别的客人进来就餐。
这里可以看出餐厅的桌子可以看出ReusableObject 可重用对象,客人就想当如客户端,整个餐厅和服务员可以看成对象池。
给出一个简单的代码

package com.example.hasee.utils;

import android.util.SparseArray;

public abstract class ObjectPool<T> {

    /**
     * 空闲的
     */
    private SparseArray<T> freePool;

    /**
     * 被使用的
     */
    private SparseArray<T> lentPoll;

    /**
     * 最大容量
     */
    private int maxCapacity;


    /**
     * 构造函数
     *
     * @param initialCapacity 初始化容量
     * @param maxCapacity     最大容量
     */
    public ObjectPool(int initialCapacity, int maxCapacity) {
        initialize(initialCapacity);
        this.maxCapacity = maxCapacity;
    }

    public ObjectPool(int maxCapacity) {
        this(maxCapacity/2,maxCapacity);
    }

    /**
     * 预先创建的对象
     * @param initialCapacity
     */
    private void initialize(final int initialCapacity) {
        lentPoll = new SparseArray<>();
        freePool = new SparseArray<>();
        for (int i = 0; i < initialCapacity; i++) {
            freePool.put(i,create());
        }
    }


    /**
     * 获取对象方法
     * @return 对象
     */
    public T acquire(){
        T t = null;
        synchronized (freePool){
            int freeSize = freePool.size();
            for (int i = 0; i < freeSize; i++) {
                //通过位置查找key的值
                int key = freePool.keyAt(i);
                //获取对象
                t = freePool.get(key);
                if(t != null){
                    //被借出去了,lentPoll加入该对象
                    this.lentPoll.put(key,t);
                    //同理,空闲的移除
                    this.freePool.remove(key);
                    return t;
                }

            }
            //为空时,并且借出的大小 加上 空闲大小 小于 总容量,说明可以创建 要不然只能等待
            if(t == null && lentPoll.size() + freeSize < maxCapacity){
                t = create();
                lentPoll.put(lentPoll.size() + freeSize,t);
            }
        }
        return t;
    }

    /**
     * 创建对象,子类实现
     * @return t
     */
    protected abstract T create();

    public void release(T t){
        if(t == null){
            return;
        }
        int key = lentPoll.indexOfValue(t);
        restore(t);
        this.freePool.put(key,t);
        this.lentPoll.remove(key);
        
    }

    /**
     * 重置对象
     * @param t
     */
    protected  void restore(T t){
    	//重置这块 可以自己定义 不一定null就是初始化状态
        t = null;
    };


}

享元模式
思想

通过节省所有对象共享状态,以减少载入内存的量。客户所请求的对象可分为两种类型的状态。

  • Internal state:内部状态。 由所有能够唯一标识一个对象的字段组成,并且这些字段不能与其他对象共享。
  • External state:外部状态。在所有可交换对象之间能够共享的字段组合。

所以享元模式所做的是,为所有对象只创建一个实例,实例内部状态的重用,减少复制它所带来的消耗。
享元模式流程图

使用范围

享元模式适用于大量粒度对象的复用,该模式只需要使用少量对象即可实现大量对象的复用,前提是这些对象的粒度小,变化性,对象之间比较相似。其内部状态存储于对象内部,一般在构造时或者通过setter函数设置,这些状态不随外界环境变化而变化。外部状态由客户报错,一般在请求的时候,会将外部状态通过参数传入对象中,这些状态随外界环境变化而变化。

角色
  • FlyWeightObjects: 享元对象。它们可以改变内部状态,并访问内部对象。
  • FlyWeightFactory: 享元工厂。当客户请求享元对象时,享元工厂负责创建享元对象,管理享元对象的内部状态。它也负责将享元对象存储在在池中,方便提供对象。
  • Clients: 客户。请求享元对象。
    实例代码


public class PackCourier implements Courier<Pack> {
    /**
     * 状态辅助类
     */
    private Van van;

    /**
     *
     * id 作为内部状态
     * @param id
     */
    public PackCourier(int id) {
        van = new Van(id);
    }

    /**
     * 该方法将外部状态传入享元对象
     */
    @Override
    public void equip(Pack param) {
        van.load(param);
    }
}

class Delivery  {
    private  Courier<Pack> courier;

    public Delivery(int id){
        courier = new Factory().getCourier(0);
    }

    /**
     * 传入外部状态
      * @param pack
     */
    public void deliver(Pack pack){
        courier.equip(pack);
    }
}

class Factory{
    private static SparseArray<Courier> pool;

    public Factory(){
        if(pool == null){
            pool = new SparseArray<>();
        }
    }

    public Courier getCourier(int type){
        Courier courier = pool.get(type);
        if(courier == null){
            courier = create(type);
            pool.put(type,courier);
        }
        return courier;
    }

    private Courier create(int type){
        Courier courier = null;
        courier = new PackCourier(type);
        return courier;
    }
}


/**
 * 外部状态
 */
class Pack {

}

class Van {

    public Van(int id) {

    }

    public void load(Pack param){

    }
}
举个例子

这种模式就好比,dota里面的英雄,分敏捷游戏,力量英雄,智力英雄。就敏捷英雄而言,如果每创造一个英雄就去生成一个新的实例,就会麻烦。但是敏捷英雄有很多共同点比如护甲,攻击力加成方式都是一样的,所以敏捷英雄的内部状态就是他的三维和成才。外部状态就是技能了。

总结

当需要大量使用对象时,减少内存的分配,也能减少垃圾回收器调用的次数。注意在使用的时候,不要无意引入内存泄漏等问题,不然白搞了。

【Android】使用对象池(Object Pool)来缓存已经创建的字节数组,避免频繁地进行内存分配和回收操作提高性能 在get()方法中,我们从队列中获取一个字节数组,如果队列为空,则创建一个新的字节数组。但是,如果我们频繁地创建和销毁字节数组,就可能会导致堆内存不足,并触发GC,从而影响应用程序的性能。在使用时,我们可以将ByteArrayPool对象作为成员变量存储在类中,并在需要使用字节数组时从对象池中获取,使用完毕后将字节数组放回对象池中。这样可以避免频繁地创建和销毁字节数组,从而提高应用程序的性能。为了避免频繁地创建和销毁字节数组,我们可以使用对象池(Object Pool)来缓存已经创建的字节数组。 阅读详情

相关推荐

Android源码设计模式探索与实战【享元模式】

理解: 享元模式是行为型设计模式的一种。依然老办法,我们想从字面意思理解一下,“享”正常我们理解这个字,在现实生活中,有享受、共享的意思,转换到代码的世界中,那么靠的上边的应该是共享。“元”,最近网络流行一个词语,元宇宙,代表根本、本源的意思,这里可以这样理解。那么从这两个字结合理解,享元模式应该是用于共享对象的一种设计模式。那么有一个问题,为什么要共享对象?我们知道,在编程过程中,不可避免的要使用到内存,对象如果大规模创建,会带来内存溢出和GC频繁导致卡顿的问题。享元模式是对象池的一种实现,它用来尽可能的

itbird的专栏 960

Android 性能优化系列 - 03 使用对象池优化内存

避免在循环里面或者频繁被调用的方法里面创建对象,在循环或者被频繁调用的方法之外创建对象使用对象池缓存对象,在使用对象的时候,直接从对象池中取对象即可,避免频繁的创建对象一般来讲,实现对象池有三种方法,对应的具体的数据结构即是数组、链表和 Map,下面我将通过示例分别介绍通过这三种数据结构实现的对象池首先是Pool<T>接口定义,代码不难,如下所示,只有两个方法acquire()和方法acquire():从对象池中取一个对象,注意:有可能会返回 null:将一个对象释放到对象池中,

Dream It Possible 1070

ObjectPool:Android 对象池

Android 对象池 谨慎和智能地使用系统资源对 Android 来说至关重要。 过度消耗堆内存会带来OutOfMemory异常和无数次遇到垃圾收集器(GC)。 GC会占用 UI 线程的宝贵时间,并且会导致丢弃 UI 帧,从而提供糟糕的用户体验。 通过重用防止触发GC 的已分配对象来解决该问题的常用方法之一。 来自维基: 对象池模式是一种软件创建设计模式,它使用一组随时可用的初始化对象——一个“池”——而不是按需分配和销毁它们。 池的客户端将从池中请求一个对象并对返回的对象执行操作。 当客户端完成后,它将对象返回到池中而不是销毁它; 这可以手动或自动完成。 对象池主要用于性能:在某些情况下,对象池可显着提高性能。 对象池使对象生命周期复杂化,因为此时从池中获取和返回的对象实际上并未创建或销毁,因此在实现时需要小心。 用法 在里面 创建ObjectPool来托管对象。 对象池提供了两

Java-Android对象池

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33806509的博客 144

CST局部网格加密实战:从基础设置到Meshgroup高效管理

本文详细解析了CST电磁仿真软件中的局部网格加密技术,重点介绍Meshgroup功能的高效管理方法。通过平行板电容等实战案例,阐述从基础设置到多级加密策略的完整流程,帮助用户精准提升关键区域仿真精度,同时优化计算资源使用效率。

grafana6viz的博客 694

如何在Proteus中模拟Arduino

进一步的Proteus可用于设计任何与Arduino相关的项目,它将在进入硬件级别之前提供更好的理解。由于其广泛的库集合,它是Arduino社区中最受欢迎的工具之一,不仅如此,Proteus还可以为Arduino项目设计定制的PCB。就像上一步一样,现在搜索Arduino UNO板,选择Arduino板并单击“确定”以添加到项目中,或者双击以在Proteus项目中添加Arduino。一旦在Proteus中成功创建了一个新项目,现在我们将设计一个用于Proteus中闪烁LED的Arduino电路。

acktomas的博客 1万+

android+对象池使用,Android开发中对高并发对象池的重复利用

这两天在整理一套Android的路由框架,在整理的过程中,发现在路由消息传递过程中,传输载体类会大量的生成,对于这种载体类来说,他们本身是可重复利用的,并不需要大量的创建,大量的废弃,所以,我打算引入对象池,来解决类的重复创建问题。 对象的生命周这两天在整理一套Android的路由框架,在整理的过程中,发现在路由消息传递过程中,传输载体类会大量的生成,对于这种载体类来说,他们本身是可重复利用的,并...

weixin_39715997的博客 439

汽车BMS技术分享及其HIL测试方案

在全球碳中和目标的战略驱动下,新能源汽车产业正以指数级速度重塑交通出行格局。动力电池作为电动汽车的"心脏",其性能与安全性不仅直接决定了车辆的续航里程、使用寿命等关键指标,更深刻影响着消费者对电动汽车的市场接受度。而电池管理系统(Battery Management System, BMS)是动力电池安全运行与性能释放的核心技术支撑。

Speedgoat的博客 2683

Android性能优化系列:如何合理使用内存

内存性能优化简介: Android系统通过在Android Lollipop替换Dalvik为ART,且在Android N添加JIT的方式提升编译安装性能 对象内存管理,避免内存抖动、内存泄漏 按需要提供变量的基本数据类型 避免自动装箱拆箱的转换 在某些场景使用Android提供的SparseArray集合组和ArrayMap代替HashMap能达到内存高效 尽量使用fo...

Vincent的博客 737

Halcon手眼标定实战:从九点标定到机械臂精准抓取(附完整代码)

本文详细介绍了Halcon手眼标定技术在实际工业场景中的应用,重点讲解了九点标定法在机械臂精准抓取中的实现步骤和优化技巧。通过对比Eye-to-Hand和Eye-in-Hand两种模式的特点,提供完整的代码示例和误差分析,帮助工程师快速掌握标定技术,提升自动化系统的精度和稳定性。

weixin_29100927的博客 459

强化学习从基础到进阶-常见问题和面试必知必答[7]:深度确定性策略梯度DDPG算法、双延迟深度确定性策略梯度TD3算法详解

强化学习从基础到进阶-常见问题和面试必知必答[7]:深度确定性策略梯度DDPG算法、双延迟深度确定性策略梯度TD3算法详解

丨汀、的博客 511

内存线程网络

内存 数据类型 byte 1 字节 8bit short 2 字节 16bit int 4 字节 32 bit long 8 字节 64bit float 4 字节 32bit double 8 字节 64bit boolean 1 字节 8bit chart 2 字节 16bit 自动装箱 基本类型与包装类之间的自动转换 ...

zhangguangtao1207的专栏 210

观测器选择与工程实践建议

摘要:永磁同步电机(PMSM)无传感器控制中,观测器选型需综合考虑应用场景、性能需求与成本。消费级(家电、工具)推荐滑模观测器(SMO),成本低、鲁棒性强;工业级(伺服、泵阀)适用扩展卡尔曼滤波器(EKF),精度高但计算复杂;车规级(EPS、主驱动)需混合观测器(SMO+EKF),兼顾全速域性能与可靠性。低速时需高频注入法,IPMSM更适用。SMO易实现但存在抖振,EKF调试复杂。未来趋势是混合架构与AI增强,提升适应性与性能。选型需权衡速度范围、电机类型、处理器能力及成本。

汽车软件开发 145

Android 源码的享元模式

Android 源码的享元模式 享元模式介绍 享元模式是对象池的一种实现,它的英文名称叫做 Flyweight,代表轻量级的意思。享元模式用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可共享的对象,达到对象共享、避免创建过多对象的效果,这样一来就可以提升性能、避免内存移除等。 享元模式定义 使用共享对象可有效地支持大量地细粒度的对象。 Android 源码中的享元模式 Ha...

okclouderx的博客 422

069_死区效应对输出电压畸变的补偿思路

死区效应导致逆变器输出电压在过零点出现台阶畸变,引发THD升高。其本质是死区期间续流二极管钳位造成的非线性误差,与电流方向、负载大小、母线电压耦合。补偿需结合前馈(基于电流方向自适应调整偏置)与反馈(抑制残余谐波),关键在于准确判断电流方向(采用滞环滤波避免跳变)、合理设置补偿量(随负载动态调整),并注意补偿位置、极性及限幅防漂移。调试应通过差分探头、FFT频谱等手段验证效果,最终实现全负载范围内的低畸变输出。

2401_88858637的博客 21

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Android设计模式之享元模式(Flyweight Pattern)

一 享元模式介绍:1.1 使用享元模式有什么好处? 享元模式是对象池的一种实现,主要目的是用来尽可能减少内存使用量。适合于存在大量重复对象的场景,来缓存可共享的对象,达到对象共享,避免创建过多对象的效果,这样可以提升性能。1.2 关于享元对象? 享元对象中的部分状态可以共享,可以共享的状态为内部状态(内蕴状态),内部状态不会随环境变化,不可共享的状态是外部状态(外蕴状态),外部状态随外部环境

happy_horse的博客 1989

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

android设计模式之享元模式

享元模式是对象池的一种实现,它的英文名是Flyweight,代表轻量级的意思。享元模式用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可共享的对象。从而达到对象共享、避免创建过多对象的效果,这样一来就可以提升性能、内存溢出等问题。 享元对象中的部分状态是可以共享的,可以共享的状态称为内部状态,内部状态不会随着环境的变化而变化;不可共享的状态称为外部状态,它们会随着环境的改变...

且听真言 535

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

android中的享元模式,Android 享元模式

一、前言享元模式即:Flyweight,它是对象池的一种实现。享元模式用来尽可能的减少内存的使用量。多用于存在大量重复对象的场景,或需要缓冲池的时候。用来缓存共享的对象。这样来避免内存移除等。二、定义运用共享技术有效的支持大量细粒度的对象。三、例子现在我们大概了解了什么是享元模式,概念再多不如一个简单例子来的痛快。下面我讲解一个查询巴士车票的例子来讲解什么是享元模式。3.1、定义巴士车票publi...

weixin_28799111的博客 419

Android设计模式-享元模式

1.享元模式Flyweight 享元模式使用共享对象可有效地支持大量的细粒度的对象。享元模式属于结构型模式。 享元模式常用于系统底层开发,解决系统的性能问题。多用于存在大量重复对象的场景,或需要缓冲池的时候。享元模式是对象池技术的重要实现方式,池里都是创建好的对象,无需再创建可直接拿来使用,这样减少了重复对象的创建,从而降低内存、提升性能。 Flyweight:抽象的享元角色,是产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。 ConcreteFlyweight:具体的享元角

zenmela2011的专栏 1071

Android的设计模式-享元模式

前言Android的设计模式系列文章介绍,欢迎关注,持续更新中: Android的设计模式-设计模式的六大原则 创建型模式: Android的设计模式-单例模式 Android的设计模式-建造者模式 Android的设计模式-工厂方法模式 Android的设计模式-简单工厂模式 Android的设计模式-抽象工厂模式 Android的设计模式-原型模式

四月葡萄的博客 756

Android常用设计模式-享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,主要用于减少创建对象的数量,以减少内存占用和提高性能。享元模式通过共享技术实现相同或相似对象的重用。

maoning20080808的专栏 866

Message对象复用(Android中的享元模式)

一、什么是享元模式 1、介绍 享元模式,即FlyWeight,旨在复用对象,避免重复、大量创建对象,从而节省系统资源的消耗 享元模式介绍:https://www.cnblogs.com/adamjwh/p/9070107.html 享元模式实践:https://www.jianshu.com/p/b925b8cb6494 二、Message中的实现 我们知道,Android是事件驱动机制,会有各种...

lizebin_bin的博客 1039

Android设计模式详解之享元模式

享元模式是对象池的一种实现,用来尽可能减少内存使用量,适合用于可能存在大量重复对象的场景,来缓存可共享的对象;使用共享对象可有效地支持大量的细粒度的对象;系统中存在大量的相似对象;细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份;需要缓冲池的场景;UML类图:享元对象抽象基类或者接口;具体的享元对象;享元工厂,负责管理享元对象池和创建享元对象;大幅度地降低内存中对象的数量,降低程序内存占用;

故不积跬步无以至千里 1038

01-16-11 享元模式 - Message.obtain的对象池复用

文章摘要: 享元模式通过对象复用减少内存开销,在Android中广泛应用于高频创建对象场景。Message类通过链表结构实现对象池,采用obtain()获取和recycle()回收机制,支持最大50个对象的复用。TypedArray同样采用对象池优化XML解析性能。这种实现通过同步锁保证线程安全,利用已有字段构建链表避免额外开销,在内存占用和性能之间取得平衡,有效减少了GC压力和内存碎片问题。

时代我西的博客 213

一文带你理解享元模式

享元模式是一种优化内存的设计模式,通过对象池的概念来避免频繁的创建和销毁对象,减少应用对GC造成的压力。

lotty_wh的博客 200
上一篇: 讨论android的设备唯一码
下一篇: android 注解使用
HUandroid
博客等级 码龄10年 35粉丝 113原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值