【池化技术】基于Apache组件--对象池的介绍与使用

news2024/10/5 10:06:45

文章目录

  • 一、背景
  • 二、对象池有什么特征?
  • 三、池的大小选择
  • 四、运行原理
  • 五、对象管理
    • 5.1添加对象
    • 5.2借用对象
    • 5.3归还对象
    • 5.4对象状态
  • 六、对象池的使用
    • 6.1 接入
    • 6.2 实现线程池工厂
    • 6.3 初始化
  • 七、优缺点
  • 八、应用场景
    • 8.1Redis应用
    • 8.2 Web服务器例子
    • 8.3 游戏开发种的例子
  • 九、总结

一、背景

减少频繁创建和销毁对象带来的成本,实现对象的缓存和复用,创建对象的成本比较大,并且创建比较频繁。比如线程的创建代价比较大,于是就有了常用的线程 池。对象池(模式)是一种创建型设计模式,它持有一个初始化好的对象的集合,将对象提供给调用者。

对象池模式是软件开发中广泛使用的设计模式,旨在通过重用创建成本高昂的对象来提高应用程序性能和效率。它在创建对象的新实例非常耗时且对象创建频率很高的情况下特别有用。当可以创建的对象实例数量由于资源限制而受到限制时,此模式也很有用。

一般而言对于 创建对象的成本比较大,并且创建比较频繁。比如线程的创建代价比较大,于是就有了常用的线程池。

二、对象池有什么特征?

一般来说,对象池有下面几个特征:

  1. 对象池中有一定数量已经创建好的对象
  2. 对象池向用户提供获取对象的接口,当用户需要新的对象时,便可通过调用此接口获取新的对象。如果对象池中有事先创建好的对象时,就直接返回给用 户;如果没有了,对象池还可以创建新的对象加入其中,然后返回给用户
  3. 对象池向用户提供归还对象的接口,当用户不再使用某对象时,便可通过此接口把该对象归还给对象池

三、池的大小选择

通常情况下,我们需要控制对象池的大小如果对象池没有限制,可能导致对象池持有过多的闲置对象,增加内存的占用。如果对象池闲置过小,没有可用的对象时,会造成之前对象池无可用的对象时,再次请求出现的问题。

对象池的大小选取应该结合具体的使用场景,结合数据(触发池中无可用对象的频率)分析来确定。现在Java的对象分配操作不比c语言的malloc调用慢, 对于轻中量级的对象, 分配/释放对象的开销可以忽略不计,并发环境中, 多个线程可能(同时)需要获取池中对象, 进而需要在堆数据结构上进行同步或者因为锁竞争而产生阻塞, 这种开销要比创建销毁对象的开销高数百倍;由于池中对象的数量有限, 势必成为一个可伸缩性瓶颈;很难正确的设定对象池的大小, 如果太小则起不到作用, 如果过大, 则占用内存资源高。
​ 空间换时间的折中,本质上,对象池属于空间换时间的折中。它通过缓存初始化好的对象来提升调用者请求对象的响应速度。除此之外,折中(tradeoff)是软件开发中的一个重要的概念,会贯穿整个软件开发过程中。

四、运行原理

在这里插入图片描述
通过对象池获取对象,可能是通过工厂新创建的,也可能是空闲的对象;当对象获取成功且使用完成后,需要归还对象;在案例执行过程中,不断查询对象池中空闲和活跃对象的数量,用来监控池的变化。

五、对象管理

5.1添加对象

创建一个新对象并且放入池中,通常应用在需要预加载的场景中;涉及到两个核心操作:工厂创建对象,对象池化管理;

public void GenericObjectPool.addObject() throws Exception ;

5.2借用对象

public T GenericObjectPool.borrowObject(final long borrowMaxWaitMillis) throws Exception ;

在这里插入图片描述

首先从队列中获取对象;如果没有获取到,调用工厂创建方法,之后池化管理;对象获取之后会改变状态为ALLOCATED使用中;最后经过工厂的确认,完成对象获取动作;

5.3归还对象

public void GenericObjectPool.returnObject(final T obj)

在这里插入图片描述

归还对象的时候,首先转换为池化对象和标记RETURNING状态;经过多次校验判断,如果失败则销毁该对象,并重新维护对象池中可用的空闲对象;最终对象被标记为空闲状态,如果不超出最大空闲数,则对象被放到队列的某一端;

5.4对象状态

关于池化对象的状态在PooledObjectState类中有枚举和描述,在图中只是对部分几个状态流转做示意,更多细节可以参考状态类;
在这里插入图片描述

可以参考在上述案例中使用到的DefaultPooledObject默认池化对象类中相关方法,结合状态枚举,可以理解不同状态之间的校验和转换。

六、对象池的使用

6.1 接入

 <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
    </dependency>

6.2 实现线程池工厂

import com.scl.online.service.model.SxInferContext;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;

 /**
 * 实现PooledObjectFactory 
 * 
 */
public class InferContextPooledObjectFactory implements PooledObjectFactory<SxInferContext> {

  @Override
  public PooledObject<SxInferContext> makeObject() {
    SxInferContext inferContext = new SxInferContext();
    return new DefaultPooledObject<>(inferContext);
  }

  @Override
  public void destroyObject(PooledObject<SxInferContext> pooledObject) {

  }

  @Override
  public boolean validateObject(PooledObject<SxInferContext> pooledObject) {
    return true;
  }

  @Override
  public void activateObject(PooledObject<SxInferContext> pooledObject) {
    pooledObject.getObject().initObject();
  }

  @Override
  public void passivateObject(PooledObject<SxInferContext> pooledObject) {
    // 当ObjectPool实例返还池中的时候调用
    pooledObject.getObject().initObject();
  }
}

说明:

  1. SxInferContext:为对象池里头的对象,对象借还都会调用到PooledObjectFactory里头的方法
  2. PooledObjectFactory负责管理PooledObject,如:借出对象,返回对象,校验对象,有多少激活对象,有多少空闲对象。
方法描述
makeObject用于生成一个新的ObjectPool实例
activateObject每一个钝化(passivated)的ObjectPool实例从池中借出(borrowed)前调用
validateObject可能用于从池中借出对象时,对处于激活(activated)状态的ObjectPool实例进行测试确保它是有效的。也有可能在ObjectPool实例返还池中进行钝化前调用进行测试是否有效。它只对处于激活状态的实例调用
passivateObject当ObjectPool实例返还池中的时候调用
destroyObject当ObjectPool实例从池中被清理出去丢弃的时候调用(是否根据validateObject的测试结果由具体的实现在而定)

6.3 初始化

public GenericObjectPool<SxInferContext> contextPools;

@PostConstruct
  public void init() {
    if (sxInferConfig.isObjectPoolUsable()) {
      InferContextPooledObjectFactory factory = new InferContextPooledObjectFactory();
      //设置对象池的相关参数
      GenericObjectPoolConfig poolConfig = initConfig();
      //新建一个对象池,传入对象工厂和配置
      contextPools = new GenericObjectPool<>(factory, poolConfig);
    }
  }


   /**
   \* 池子初始化
   *
   \* @param
   */
  public GenericObjectPoolConfig initConfig() {
    GenericObjectPoolConfig cfg = new GenericObjectPoolConfig();
    cfg.setJmxNamePrefix("objectPool");
    //  对象总数
    cfg.setMaxTotal(sxInferConfig.getPoolMaxTotal());
    // 最大空闲对象数
    cfg.setMaxIdle(sxInferConfig.getPoolMaxIdle());
    // 最小空闲对象数
    cfg.setMinIdle(sxInferConfig.getPoolMinIdle());
    // 借对象阻塞最大等待时间
    // 获取资源的等待时间。blockWhenExhausted 为 true 时有效。-1 代表无时间限制,一直阻塞直到有可用的资源
    cfg.setMaxWaitMillis(sxInferConfig.getPoolMaxWait());
    // 最小驱逐空闲时间
    cfg.setMinEvictableIdleTimeMillis(sxInferConfig.getPoolMinEvictableIdleTimeMillis());
    // 每次驱逐数量  资源回收线程执行一次回收操作,回收资源的数量。默认 3
    cfg.setNumTestsPerEvictionRun(sxInferConfig.getPoolNumTestsPerEvictionRun());
    // 回收资源线程的执行周期,默认 -1 表示不启用回收资源线程
    cfg.setTimeBetweenEvictionRunsMillis(sxInferConfig.getPoolTimeBetweenEvictionRunsMillis());
    // 资源耗尽时,是否阻塞等待获取资源,默认 true
    cfg.setBlockWhenExhausted(sxInferConfig.isPoolBlockWhenExhausted());
    return cfg;
  }

说明:cfg.setJmxNamePrefix(“objectPool”); 假如项目中有用到redis线程池,则需要配置一下JmxNamePrefix。redis线程池使用的是“pool”,假如有重复的,早调用线程池是时,就默认会调用到Redis线程池的PooledObjectFactory(假如redis线程池使用默认的话),导致配置的线程池不生效。

GenericObjectPool 方法解释:
GenericObjectPool 方法解释:

方法描述
borrowObject从池中借出一个对象。要么调用PooledObjectFactory.makeObject方法创建,要么对一个空闲对象使用PooledObjectFactory.activeObject进行激活,然后使用PooledObjectFactory.validateObject方法进行验证后再返回
returnObject将一个对象返还给池。根据约定:对象必须 是使用borrowObject方法从池中借出的
invalidateObject废弃一个对象。根据约定:对象必须 是使用borrowObject方法从池中借出的。通常在对象发生了异常或其他问题时使用此方法废弃它
addObject使用工厂创建一个对象,钝化并且将它放入空闲对象池
getNumberIdle
getNumActive返回从借出的对象数量。如果这个信息不可用,返回一个负数
clear清除池中的所有空闲对象,释放其关联的资源(可选)。清除空闲对象必须使用PooledObjectFactory.destroyObject方法
close关闭池并释放关联的资源

七、优缺点

  • 对象池优点

    • 提高性能,对象池模式可以通过减少与对象创建和销毁相关的开销来显着提高应用程序的性能。通过重用预先初始化的对象,该模式减少了需要创建的对象数量,进而减少了创建新对象所需的时间和资源。
    • 资源管理,对象池模式提供了一种管理共享资源的机制,例如数据库连接或文件句柄。通过限制创建的对象数量,该模式可以防止资源耗尽并确保资源得到有效共享。
    • 一致性,对象池模式可以通过确保所有对象在使用前都预先初始化为已知状态来帮助确保应用程序的一致性。这在对象初始化复杂或耗时的情况下特别有用。
    • 易于实现,对象池模式相对容易实现,可用于多种情况。它是一种经过验证的设计模式,已在许多应用程序和编程语言中成功使用。
  • 对象池缺点

    • 增加复杂性,对象池模式可以通过添加额外的抽象层来增加应用程序的复杂性。这会使代码更难理解和维护,尤其是在池大小和对象生命周期管理不当的情况下。
    • 开销,虽然对象池模式可以通过减少与对象创建和销毁相关的开销来提高性能,但由于池本身的管理,它也会引入额外的开销。如果池大小没有针对应用程序的需要进行优化,这种开销会变得很大。
    • 有限的灵活性:对象池模式旨在管理一组固定的对象,可能不适合需要动态对象创建或可变池大小的应用程序。
    • 线程安全,如果多个线程同时访问池,对象池模式会引入线程安全问题。同步机制必须到位以确保一次只有一个线程可以访问池,这可能会增加额外的开销和代码的复杂性。
    • 资源泄漏,如果对象没有正确返回到池中,它们可能会“泄漏”并且无法重用。随着时间的推移,这会导致资源耗尽并降低应用程序性能。

八、应用场景

8.1Redis应用

Lettuce作为Redis高级的客户端组件,通信层使用Netty组件,并且是线程安全,支持同步和异步模式,支持集群和哨兵模式;作为当下项目中常用的配置,其底层对象池基于common-pool2组件。

8.2 Web服务器例子

Web 服务器通常需要处理大量并发请求,这会给系统资源带来巨大压力。通过使用对象池来管理数据库连接、网络套接字或其他资源,从而提高Web 服务器的性能和可扩展性,避免资源耗尽。

8.3 游戏开发种的例子

游戏通常需要快速创建和销毁大量对象,例如粒子、子弹或敌人。通过使用对象池来管理这些对象,游戏可以提高性能并减少与对象创建和销毁相关的开销。

九、总结

对象池模式是一种强大的设计模式,可以通过重用昂贵的对象显著提高应用程序性能和效率。它提供了一种管理共享资源的机制,并通过限制创建的对象数量来防止资源耗尽。如果使用得当,对象池模式可以成为提高软件应用程序的可伸缩性和可靠性的有效工具。

本文从对象池的一个简单案例切入,主要分析common-pool2组件关于:池、工厂、配置、对象管理几个角色的源码逻辑,并且参考其在Redis中的实践,只是冰山一角,像这种通用型并且应用范围广的组件,很值得时常去读一读源码,真的令人惊叹其鬼斧天工的设计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/539903.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

论文中文翻译——Double-Fetch情况如何演变为Double-Fetch漏洞:Linux内核中的双重获取研究

本论文相关内容 论文下载地址——Web Of Science论文中文翻译——How Double-Fetch Situations turn into Double-Fetch Vulnerabilities A Study of Double Fetches in the Linux Kernel 文章目录 本论文相关内容前言Double-Fetch情况如何演变为Double-Fetch漏洞&#xff1a;…

Elasticsearch:如何使用 Elasticsearch 以自然语言提示 ChatGPT

作者&#xff1a;Enrico Zimuel 这些天每个人都在谈论 ChatGPT。 这种大型语言模型 (LLM) 的一项很酷的功能是能够生成代码。 我们用它来生成 Elasticsearch DSL 查询。 目标是在 Elasticsearch 中搜索 “给我股票指数中 2017 年的前 10 个文档&#xff08;Give me the first 1…

C/C++web编程,以及案例(内附小白基础知识)你也能轻松学会呦~

目录 C基本知识&#xff0c;小白来这里 C 基本的输入输出 I/O 库头文件 标准输出流&#xff08;cout&#xff09; 标准输入流&#xff08;cin&#xff09; 标准错误流&#xff08;cerr&#xff09; 标准日志流&#xff08;clog&#xff09; Cweb编程&#xff0c;老手来这…

【人工智能】蚁群算法(密恐勿入)

蚁群算法&#xff08;密恐勿入&#xff09; 蚁群算法--给你一个感性认识 蚁群算法&#xff08;密恐勿入&#xff09;1. 算法简介1.1 基本原理1.1.1 模拟蚂蚁在简单地形&#xff0c;寻找食物1.1.2 模拟蚂蚁在复杂地形&#xff0c;找到食物1.2 算法应用 2. 算法解析3.算法应用——…

Spark 2:Spark Core RDD算子

RDD定义 RDD&#xff08;Resilient Distributed Dataset&#xff09;叫做弹性分布式数据集&#xff0c;是Spark中最基本的数据抽象&#xff0c;代表一个不可变、可分区、里面的元素可并行计算的集合。 Resilient&#xff1a;RDD中的数据可以存储在内存中或者磁盘中。 Distribut…

Jenkins入门使用详解,实现构建部署运行

Hi I’m Shendi Jenkins入门使用详解&#xff0c;实现构建部署运行 Jenkins简介 Jenkins 是一个用 Java 编写的开源自动化工具 Jenkins是一款开源 CI&CD 软件&#xff0c;用于自动化各种任务&#xff0c;包括构建、测试和部署软件。 CI 指持续集成&#xff0c;属于开发人…

【数据结构】--单链表力扣面试题①移除链表元素

题述&#xff1a; 给你一个链表的头结点head和一个整数val,请你删除链表中所有满足Node.val val的节点&#xff0c;并返回新的头结点。 思考&#xff1a; 为什么说要返回新的头结点&#xff0c;因为你删除的可能存在把原来的头结点删除的情况&#xff0c;这时就需要有新的头结…

【机器学习】

说明&#xff1a;机器学习总结 0、数据集 1、贝叶斯分类器 &#xff08;一&#xff09;计算题 所有样本分为两类&#xff08;c &#xff09;&#xff1a;好瓜是、好瓜否 &#xff08;1&#xff09;计算先验概率&#xff1a;P(c ) &#xff08;2&#xff09;计算每个属性的条…

元宇宙:梦想能否照进现实?

开篇我想问大家一个问题&#xff1a;有没有想过人类的未来是什么样子&#xff1f; 就目前我们所能探索的世界&#xff0c;不论从空间上有跨越了几十亿光年的距离&#xff0c;还是从时间有上几万几亿年的演化&#xff0c;对于宇宙来说&#xff0c;我们人类实在是太过渺小、脆弱…

非暴力沟通模型

非暴力沟通模型 非暴力沟通的创始人是马歇尔.卢森堡&#xff0c;师从人本主义心理学之父卡尔.罗杰斯。《非暴力沟通》一书入选香港大学推荐的50本必读书籍之列。 模型介绍 非暴力沟通&#xff08;英文名称&#xff1a;NonviolentCommunication&#xff0c;简称NVC&#xff09;…

AMBER分子动力学模拟之结果分析(MMGB/PBSA)-- HIV蛋白酶-抑制剂复合物(4)

AMBER分子动力学模拟之结果分析(MMGB/PBSA)-- HIV蛋白酶-抑制剂复合物(4) 结合自由能计算 我们首先计算焙变&#xff0c;用到的是pbsa和gbsa方法。我们需要一下文件 三个top文件&#xff0c;pro.prmtop lig.prmtop com.prmtop&#xff1b;输入文件MM_GBSA.in&#xff1b;将要…

Nextcloud集成Onlyoffice实现协同办公。

Nextcloud 安装 LAMP&#xff08;LinuxApacheMySQLPHP&#xff09;方式。局域网单机模式。 安装环境&#xff1a; OS:ubuntu 22.04 Nextcloud&#xff1a;26 Apache&#xff1a;2.4.52 mysql&#xff1a;Server version: 8.0.33-0ubuntu0.22.04.1 (Ubuntu) php:PHP 8.1.2-1u…

(GCC)从零开始的ETH开发--STM32F407ZGTX

开发环境&#xff1a; windows10 软件&#xff1a; STM32CubeMX最新版本&#xff1a; gcc工具链&#xff1a; vscode 硬件&#xff1a; STM32F407ZGT6开发板&#xff0c;ETH原理图&#xff1a; ​ 根据硬件可知MAC和PHY之间的接口类型为RMII&#xff0c;且PHY使用的外…

【文老师软考数据库】(全)

目录 第一章 计算机系统基本知识 1.1 计算机系统 1.1.1 计算机硬件组成 1.1.2 中央处理单元 1.1.3 数据表示 1.1.4 校验码 1.2 计算机体系结构 1.2.1 体系结构分类 1.2.2 指令系统存 1.2.3 储系系统 1.2.4 输入/输出技术 1.2.5 总线结构 1.3 可靠性、性能、安全 …

Win10系统为什么又提示重装打印机驱动?

明明没干嘛&#xff0c;Win 10系统却提示需要重新安装打印机驱动程序。驱动人生就来说说Win10重新安装打印机驱动程序的原因及解决方法&#xff1a; 一般来说&#xff0c;如果用户更新了Win 10的操作系统&#xff0c;可能导致之前的打印机驱动错误或缺失&#xff0c;这时候就需…

运行KT001小车问题汇总

运行KT001小车问题汇总&#xff1a; Q: 在安装ros的时候&#xff0c;出现这样的问题是因为什么&#xff0c;是镜像文件里边缺少东西了吗&#xff0c;可以怎么解决&#xff1f; A: 导入的是vmk配置文件&#xff0c;缺少iso镜像文件&#xff0c;不影响ros的运行。 Q: 编辑好这个…

Android ANativeWindow 渲染画面

ANativeWindow 是 Android NDK&#xff08;Native Development Kit&#xff09;提供的一个C/C编程接口&#xff0c;用于与底层的图形系统进行交互&#xff0c;实现图像渲染和处理等功能。 使用方法&#xff1a;上层用 SurfaceView&#xff0c;传递 SurfaceView 的 Surface 给 n…

ChatGPT的插件能用了,每月 20 美元的实习生真香

文章目录 开启插件并使用其他补充缺点和不足总结 哈喽嗨&#xff01;你好&#xff0c;我是小雨青年&#xff0c;一名 追赶 AI 步伐的程序员。 自从上周 OpenAI 官宣了即将开放插件给 Plus 用户以来&#xff0c;这三天我就每天都会刷新ChatGPT 设置页面。 直到今天早上&#x…

SolVES模型应用(生态系统服务社会价值模型)

生态系统服务是人类从自然界中获得的直接或间接惠益&#xff0c;可分为供给服务、文化服务、调节服务和支持服务4类&#xff0c;对提升人类福祉具有重大意义&#xff0c;且被视为连接社会与生态系统的桥梁。自从启动千年生态系统评估项目&#xff08;Millennium Ecosystem Asse…

思迈特软件Smartbi荣登“2023未来银行科技服务商100强”

近日&#xff0c;中国科学院《互联网周刊》、eNet研究院联合发布了“2023未来银行科技服务商100强”企业榜单。思迈特软件以“商业智能BI产品”凭借在金融科技创新的独特优势及在银行数字化转型实践中的卓越成就荣耀上榜。 据了解&#xff0c;“未来银行科技服务商100强”榜单&…