如何构建一个对象池并使用

这篇具有很好参考价值的文章主要介绍了如何构建一个对象池并使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.背景

在项目中,如果频繁的通过new 创建对象,之后让gc再去回收,这就很容易造成内存抖动,并且频繁的GC本身也会消耗内存,这样就很容易在一瞬间造成OOM 内存溢出,因为瞬间申请大量内存会造成内存占用突然升高,如果GC 还没来的及回收,或者频繁GC,内存就会居高不下,这时有两种处理方式,一个是减少对象的创建,一个是复用对象。

2. 对象复用的基本原理

所谓对象复用,就是在对象创建使用完成后将对象内部的数据清除,然后将对象放到缓存中,等到下次需要创建新对象时拿出来复用,这样一来一回,只需要占用固定的内存就可以,不用每次都去new 一个对象申请内存,即避免的内存抖动,又避免了频繁GC,造成可能的稳定性问题,但是也有一个小弊端,就是这块缓存的对象所占的对象是固定的,无法随着GC来回收,如果需要回收需要我们手动处理,所以这个就需要我们对使用场景来评估。

3.如何构建一个对象池

1.需要有一个合适的对象
2.定一个对象池的大小
3.处理对象的回收
4.在核实的位置获取对象池中数据并且在使用完成后回收

4. 构建一个对象池

public class MapCache extends HashMap<String, String> {
    private static final String TAG = "MapCache";
    //下一条对象
    MapCache next;
    public static final Object sPoolSync = new Object ();
    // 链表首个对象
    private static MapCache sPool;
    //当前链表个数
    private static int sPoolSize = 0;
    //可缓存的最大空闲对象数量,超出后将开始new 对象,由GC 处理回收
    private static final int MAX_POOL_SIZE = 50;

    @Override
    public void clear() {
       recycle ();
    }

    /**
     * 获取map对像,如果对象池存在空闲对象,就从头部取出一个空对象返回
     * 否则new 一个新对象。
     */
    public static MapCache obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                MapCache m = sPool;
                sPool = m.next;
                m.next = null;
                sPoolSize--;
                // 返回链表头部对象
                return m;
            }
        }
        return new MapCache ();
    }

    /**
     * 回收对象资源
     */
    private void recycle() {
        super.clear ();
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                // 将当前消息放到链表头部
                sPool = this;
                //链表消息池对象增加1
                sPoolSize++;
            }
        }
    }
    public static MapCache createCacheMap(Map<String, String> args) {
        MapCache map = obtain ();
        for (Map.Entry<?, ?> entry : args.entrySet ()) {
            String key = (String) entry.getKey ();
            if (key == null) {
                Log.e (TAG, "CreateMap error: key == null");
                continue;
            }
            map.put (key, (String) entry.getValue ());
        }
        return map;
    }
    private static boolean isMapCache(Map mapCache) {
        if (mapCache instanceof MapCache) {
            return true;
        }
        return false;
    }
    public static MapCache createMap(Map mapCache) {
        if (mapCache==null || mapCache.size ()<=0) {
            return null;
        }
        if (isMapCache(mapCache)) {
            return (MapCache) mapCache;
        }
        return createCacheMap (mapCache);
    }

}

其实还算简单,基本原理就是定一个对象池大小,用一个链表来存储对象,然后定义一个静态的头部对象sPoolSync,然后定义这个头部对象的next 指向的下一个对象,这样就形成了一个链表的对象池。

3.1 获取对象

当通过obtain() 方法来获取一个对象时,如果链表中有缓存的对象数据就取出链表首部的对象,然后将他的下一个对象指向头部对象,然后将对象池减一个,如果没有足够的对象或者首次调用,那就new 一个对象返回。

3.2 对象的回收

对象内容的回收recycle()需要根据不同的对象定义来处理,就比如我这定义的HashMap,使用完成后只需要调用clear 方法将原数据清空,然后将这个对象加入到线程池中即可。
具体操作 就是先将当前的链表头部对象指向当前的空闲对像的next,然后将空闲该对象 指向头部静态对像,然后对象池加一,这样就顺利将空闲对像加到链表头部。文章来源地址https://www.toymoban.com/news/detail-646865.html

到了这里,关于如何构建一个对象池并使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 面试题:如何知道java对象被垃圾回收掉,用代码实现一个能监听对象被回收的功能

    Java中无法直接判断一个对象是否被垃圾回收掉,因为Java的垃圾回收机制是自动的,程序员并不需要手动清理对象。但是,如果我们想要知道一个对象何时被回收掉,可以使用 finalize() 方法。 每个Java对象都有一个 finalize() 方法,这个方法会在对象被垃圾回收前调用一次。我们

    2024年02月02日
    浏览(43)
  • JVM 内存分哪几个区,如和判断一个对象是否存活

    JVM 内存分哪几个区,每个区的作用是什么 ? java 虚拟机主要分为以下一个区 : 方法区: 1. 有时候也成为 永久代 ,在该区内很少发生垃圾回收,但是并不代表不发生  GC ,在这里进行的  GC 主要是对方法区里的常量池和对类型的卸载 2. 方法区主要用来存储已被虚拟机加载的类

    2024年02月05日
    浏览(41)
  • 设计模式之美-实战二:如何对接口鉴权这样一个功能开发做面向对象分析?

            面向对象的三个环节:面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程(OOP)。只知道OOA、OOD、OOP只能说有一个宏观了解,我们更重要的还是要知道“如何做”,也就是,如何进行面向对象分析、设计与编程。         本文结合一个真实的开发案例,从基

    2024年02月09日
    浏览(48)
  • 【iOS分类、关联对象】如何使用关联对象给分类实现一个weak的属性

    如何使用关联对象给分类实现一个weak的属性 通过关联对象objc_setAssociatedObject中的策略policy可知,并不支持使用weak修饰对象属性: 思考:能否用assign实现? weak和assign的区别如下: **assign:**对应的所有权类型为__unsafe_unretained,当修饰对象的时候,修饰的指针指向该对象,不

    2024年02月21日
    浏览(45)
  • 如何构建一个 NodeJS 影院微服务并使用 Docker 部署

    如何构建一个 NodeJS 影院微服务并使用 Docker 部署。在这个系列中,将构建一个 NodeJS 微服务,并使用 Docker Swarm 集群进行部署。 以下是将要使用的工具: NodeJS 版本7.2.0 MongoDB 3.4.1 Docker for Mac 1.12.6 在尝试本指南之前,应该具备: NodeJS 的基本知识 Docker 的基本知识(并且已经安

    2024年02月12日
    浏览(53)
  • 三、JVM-如何判断对象已死问题

    体验与验证 2.4.5.1 使用visualvm visualgc插件下载链接 : https://visualvm.github.io/pluginscenters.html 选择对应JDK版本链接—Tools—Visual GC 若上述链接找不到合适的,大家也可以自己在网上下载对应的版本 2.4.5.2 堆内存溢出 代码 记得设置参数比如-Xmx20M -Xms20M 运行结果 访问 :http://localh

    2024年02月14日
    浏览(37)
  • JVM源码剖析之Java对象创建过程

    关于 \\\"Java的对象创建\\\" 这个话题分布在各种论坛、各种帖子,文章的水平参差不齐。并且大部分仅仅是总结 \\\"面试宝典\\\" 的流程,小部分就是copy其他帖子,极少能看到拿源码作为论证。所以特意写下这篇文章。 版本信息如下: 首先把总结图放在这。接下来分析源码~  用一个

    2024年02月12日
    浏览(47)
  • 深入JVM了解Java对象实例化过程

    new :最常见的方式、 Xxx 的静态方法, XxxBuilder/XxxFactory 的静态方法 Class的newInstance 方法:反射的方式,只能调用空参的构造器,权限必须是public Constructor的newInstance(XXX) :反射的方式,可以调用空参、带参的构造器,权限没有要求 使用 clone() :不调用任何的构造器,要求当

    2023年04月24日
    浏览(39)
  • JVM-java对象内存分布(二)

    目录 一、栈针 二、java 对象内存分布 1、那何为java内存对象布局? 2、什么是jvm的内存模型 1、如果我们新生代,一直创建新对象,此时我们新生代不够用了怎么办? 2、那么为什么大部分对象的生命周期比较短呢?这个结论哪来的呢? 3、那么为什么是这个8:1:1呢? 4、就是

    2024年02月11日
    浏览(42)
  • JVM对象在堆内存中是否如何分配?

    1:指针碰撞:内存规整的情况下 2:空闲列表: 内存不规整的情况下 选择那种分配方式 是有 java堆是否规整而决定的。而java堆是否规整是否对应的垃圾回收器是否带有空间压缩整理的能力决定的。 因此当使用Serial,ParNew等带有压缩整理过程的收集器时,系统采用的分配算法是

    2024年02月16日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包