自定义对象池BasePooledObjectFactory的使用

news2024/11/19 4:42:36

项目中用到了apache的对象池来管理文件导出相关资源连接和回收功能,因此花点时间简单了解下对象池相关使用,做点记录。

一. 连接池

频繁的建立和关闭连接,会极大的降低系统的性能,而连接池会在初始化的时候会创建一定数量的连接,每次访问只需从连接池里获取连接,使用完毕后再放回连接池,并不是直接关闭连接,这样可以保证程序重复使用同一个连接而不需要每次访问都建立和关闭连接, 从而提高系统性能。

二、场景

场景
1,资源受限的, 不需要可伸缩性的环境(cpu\内存等物理资源有限): cpu性能不够强劲, 内存比较紧张, 垃圾收集, 内存抖动会造成比较大的影响, 需要提高内存管理效率, 响应性比吞吐量更为重要;
2,数量受限的, 比如数据库连接;
3,创建成本高的对象, 可以考虑是否池化, 比较常见的有线程池(ThreadPoolExecutor), 字节数组池等。

三、自定义对象池

1 引入依赖

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

2 定义Person对象

public class Person {

    private final String name;

    public Person(String name) {
        this.name = name;
    }

    public void create() {
        System.out.println("ThreadName:" + Thread.currentThread().getName() + " 对象:" + name + "正在被创建。。。。。。");
    }

    public void destroy() {
        System.out.println("ThreadName:" + Thread.currentThread().getName() + " 对象:" + name + "正在被销毁。。。。。。");
    }

    public boolean isValid() {
        System.out.println("ThreadName:" + Thread.currentThread().getName() + " 对象" + name + "正在检验是否可用。。。。。。");
        return true;
    }
}

3 对象池

public enum MyCommonPool {
    /**
     * 线程安全的单例
     */
    INSTANCE;

    private final GenericObjectPool<Person> objectPool;

    MyCommonPool() {
        // 创建对象池配置
        GenericObjectPoolConfig<Person> poolConfig = new GenericObjectPoolConfig<>();
        // 对象池中最大对象数
        poolConfig.setMaxTotal(3);
        // 对象池中最小空闲对象数
        poolConfig.setMinIdle(1);
        // 对象池中最大空闲对象数
        poolConfig.setMaxIdle(2);
        // 当对象池耗尽时,是否等待获取对象
        poolConfig.setBlockWhenExhausted(true);
        // 创建对象时是否进行对象有效性检查
        poolConfig.setTestOnCreate(true);
        // 借出对象时是否进行对象有效性检查
        poolConfig.setTestOnBorrow(true);
        // 归还对象时是否进行对象有效性检查
        poolConfig.setTestOnReturn(true);
        // 空闲时是否进行对象有效性检查
        poolConfig.setTestWhileIdle(true);
        // 获取对象最大等待时间 默认 -1 一直等待
        poolConfig.setMaxWait(Duration.ofSeconds(2));
        // 创建对象工厂
        PersonBasePooledObjectFactory objectFactory = new PersonBasePooledObjectFactory();
        // 创建对象池
        objectPool = new GenericObjectPool<>(objectFactory, poolConfig);
    }

    /**
     * 从对象池中借出一个对象
     *
     * @return Person
     * @throws Exception
     */
    public Person borrowObject() throws Exception {
        Person zou = objectPool.borrowObject();
        int numActive = objectPool.getNumActive();
        int numIdle = objectPool.getNumIdle();
        System.out.println("ThreadName:" + Thread.currentThread().getName() + " 活跃对象数量:" + numActive + " 空闲对象数量:" + numIdle);
        System.out.println("------------------------------------------------------------");
        return zou;
    }

    public void returnObject(Person myObject) {
        // 将对象归还给对象池
        objectPool.returnObject(myObject);
    }

    /**
     * 获取活跃的对象数
     *
     * @return int
     */
    public int getNumActive() {
        return objectPool.getNumActive();
    }

    /**
     * 获取空闲的对象数
     *
     * @return int
     */
    public int getNumIdle() {
        return objectPool.getNumIdle();
    }
}

4 自定义线程池对象工厂

public class PersonBasePooledObjectFactory extends BasePooledObjectFactory<Person> {

    @Override
    public Person create() {
        // 创建一个新的MyObject对象
        Person myObject = new Person(UUID.randomUUID().toString());
        myObject.create();
        return myObject;
    }

    @Override
    public PooledObject<Person> wrap(Person myObject) {
        // 将MyObject对象封装到一个PooledObject对象中并返回
        return new DefaultPooledObject<>(myObject);
    }

    @Override
    public void destroyObject(PooledObject<Person> pooledObject) {
        // 销毁对象
        Person myObject = pooledObject.getObject();
        myObject.destroy();
    }

    @Override
    public boolean validateObject(PooledObject<Person> pooledObject) {
        // 验证对象是否可用
        Person myObject = pooledObject.getObject();
        return myObject.isValid();
    }
}

四、测试验证

1 对象池测试类

@SpringBootTest
public class PersonPoolTest {

    // 测试对象数使用情况
    @Test
    public void singleTest() throws Exception {
        // 最大对象数量3 最小空闲对象数量1 最大空闲数量 2
        MyCommonPool myObjectPool = MyCommonPool.INSTANCE;
        numActiveAndNumIdle(myObjectPool);
        // 获取对象
        Person obj = myObjectPool.borrowObject();
        // 获取对象
        Person obj2 = myObjectPool.borrowObject();
        // 获取对象
        Person obj3 = myObjectPool.borrowObject();

        // 第4次获取对象,已超出最大对象数3,则会抛出异常,线程终止
        //Person obj4 = myObjectPool.borrowObject();

        // 归还一次对象,则活跃对象-1,空闲对象+1
        myObjectPool.returnObject(obj);
        System.out.println("ThreadName:" + Thread.currentThread().getName()
                + " returned: " + JSONObject.toJSONString(obj));
        numActiveAndNumIdle(myObjectPool);
    }

    /**
     * 活跃对象数和空闲对象数
     *
     * @param myObjectPool 自定义对象池
     */
    private static void numActiveAndNumIdle(MyCommonPool myObjectPool) {
        int numActive = myObjectPool.getNumActive();
        int numIdle = myObjectPool.getNumIdle();
        System.out.println("ThreadName:" + Thread.currentThread().getName()
                + " 活跃对象数量:" + numActive + " 空闲对象数:" + numIdle);
        System.out.println("------------------------------------------------------------");
    }
}

2,当注释掉

Person obj4 = myObjectPool.borrowObject();

会根据自定义对象池参数:最大对象数量3 最小空闲对象数量1 最大空闲数量 2输出结果
在这里插入图片描述
当放开

Person obj4 = myObjectPool.borrowObject();

第4次获取对象,已超出最大对象数3,则会抛出异常,线程终止
在这里插入图片描述
源码下载 demo-springboot-mybatisplus,欢迎Star!

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

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

相关文章

HTML静态网页成品作业(HTML+CSS)—— 冶金工程专业展望与介绍介绍网页(2个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有2个页面。 二、作品演示 三、代…

教育数字展馆助力全球教育传播,科技引领数字化教育潮流

一、教育数字展馆助力教育传播 1、提高教育资源的可及性 教育数字展馆通过VR和WEB3D技术&#xff0c;将丰富的教育资源呈现在用户面前。不论是名校的经典课程&#xff0c;还是专家的精彩讲座&#xff0c;均可通过教育数字展馆实现线上展示。用户只需登录平台&#xff0c;即可…

手机耳机哪个品牌音质好

在寻找音质出色的手机耳机时&#xff0c;品牌选择显得尤为重要。市场上众多知名品牌提供了各式各样的耳机产品&#xff0c;它们在音质、降噪功能、设计等方面各有千秋。以下是一些在音质上表现优异的手机耳机品牌的分析&#xff1a; 索尼&#xff1a;索尼的耳机以其卓越的降噪技…

jenkins插件之plot

plot是一个生成图表的插件&#xff0c;这里我用于可视化phploc统计的数据 插件安装 进入 Dashboard --> 系统管理 --> 插件管理 --> Available plugins 搜索plot安装生成phploc分析数据 Dashboard --> 您的项目 --> Configuration点击 Build Steps点击 增加构…

使用 union 判断系统大小端

使用 union 判断系统大小端 大小端介绍字节序内存布局小端大端 确定大小端的方法union指针 大小端介绍 字节序 内存布局 栈空间向低地址生长&#xff0c;堆空间向高地址生长。 小端 大端 确定大小端的方法 union #include <stdio.h>// 定义一个联合体&#xff0c;包…

随身wifi和手机流量卡,你知道该怎么选吗?

网络已经成为我们这个时代的代名词&#xff01; 那么&#xff0c;在上网的时代&#xff0c;我们有很多问题都要考虑&#xff0c;比如如何选择上网方式&#xff0c;是选择一张流量卡&#xff0c;还是一个随身WIFI&#xff1f; 听小编一句劝&#xff0c;先不要着急买&#xff0c…

与牢霍沟通——Linux操作系统原理

硬件层 计算机由何组成&#xff1f; 我们现在手中的计算机&#xff0c;无论配置如何&#xff0c;是笔记本还是台式&#xff0c;都由三部分构成&#xff1a; 输入设备&#xff1a;键盘&#xff0c;鼠标...中央处理器&#xff1a;cpu&#xff0c;显卡&#xff0c;磁盘...输出设…

Mac下载docker

先安装homebrew Mac下载Homebrew-CSDN博客 然后输入以下命令安装docker brew install --cask --appdir/Applications docker 期间需要输入密码。输入完等待即可

【Flask-app.py运行】已解决Cannot run program “D:\APP\python\python.exe”

文章目录 一、问题描述二、解决方法 一、问题描述 Cannot run program “D:\APP\python\python.exe” (in directory “F:\Codes\竞赛\大计赛\group\code\web\web”): CreateProcess error2, 系统找不到指定的文件。 这段报错源于运行 flask 项目的 app.py 时报错找不到程序&…

学习Java,stringbuilder用法

有sb.append添加元素&#xff0c;sb.reverse反转内容&#xff0c;sb.tostring转换成字符串&#xff0c;sb.length计算长度。

利用WK2168实现串口服务器

ESP32 SPI与WK2168实现串口服务器 概述系统组成代码 概述 一些老设备通过RS485采集数据&#xff0c;如果在一个系统中采用几个RS485设备可能是一个不错的选择&#xff0c;但要是使用46个RS485数据采集设备为一个PLC提供外部数据&#xff0c;系统的性能就很难有保障了。通过一个…

利用二维数组的输出下列图形

利用二维数组的输出下列图形 #include <stdio.h> int main () {int i,j;char a[5][9]{{*,*,*,*,*},{ ,*,*,*,*,*},{ , ,*,*,*,*,*},{ , , ,*,*,*,*,*},{ , , , ,*,*,*,*,*}};for(j0;j<9;j) {for(i0;i<5;i) {printf("%c ",a[i][j]);} printf("\n&qu…

Ubuntu 24.04 LTS 安装Docker

1 更新软件包索引&#xff1a; sudo apt-get update 2 安装必要的软件包&#xff0c;以允许apt通过HTTPS使用仓库&#xff1a; sudo apt-get install apt-transport-https ca-certificates curl software-properties-common 3 添加Docker的官方GPG密钥&#xff1a; curl -fs…

“好喜欢”等复审被驳回,日常用语不具备商标识别作用!

在平常的商标申请注册中&#xff0c;普推知产老杨发现许多主体喜欢用日常用语申请注册注册商标&#xff0c;但是这些名称不具备商标的识别作用&#xff0c;缺乏商标所具体显著特征&#xff0c;大概率会被驳回&#xff0c;而且复审也会被驳回。 常看到一些广告宣传语&#xff0c…

K8s Ingress 详解

文章目录 K8s Ingress 详解Ingress 资源清单Ingress 基于URL 实现路由Ingress 基于名称虚拟主机Ingress 实现HTTPS创建TLS 证书创建Secrets配置ingress Ingress RewriteIngress 灰度发布Ingress 配置认证 K8s Ingress 详解 Ingress 资源清单 apiVersion: networking.k8s.io/v…

体验Photoshop:无需下载,直接在浏览器编辑图片

搜索Photoshop时&#xff0c;映入眼帘的是PS软件下载&#xff0c;自学PS软件需要多长时间&#xff0c;学PS软件有必要报班吗...PS软件的设计功能很多&#xff0c;除了常见的图像处理功能外&#xff0c;还涉及图形、文本、视频、出版等。不管你是平面设计师&#xff0c;UI/UX设计…

mac多媒体影音库:Emby for Mac 中文版

Emby软件是一款功能强大的媒体服务器软件&#xff0c;旨在为用户提供丰富的多媒体体验。以下是关于Emby软件的详细介绍&#xff1a; 下载地址&#xff1a;https://www.macz.com/mac/7964.html?idOTI2NjQ5Jl8mMjcuMTg2LjE1LjE4Mg%3D%3D 主要功能 媒体管理&#xff1a;Emby允许用…

VMWare下安装Linux虚拟机(图文)

大家好&#xff0c;在当今科技发展迅速的时代&#xff0c;虚拟化技术在企业和个人用户中变得越来越普遍。VMware作为一款领先的虚拟化软件&#xff0c;为用户提供了在单一物理计算机上运行多个操作系统的能力&#xff0c;为开发、测试和运维等任务提供了便利。在这篇文章中&…

OpenCV学习 基础图像操作 (十五):频域变换及相关操作

基础原理 图像的频域处理提供了一种强大的工具&#xff0c;用于分析和处理图像的频率成分。傅里叶变换、小波变换和Gabor变换等技术各有优劣&#xff0c;适用于不同的应用场景。通过选择合适的频域算法&#xff0c;可以实现图像的压缩、去噪、特征提取和增强等多种应用。本篇主…

每日一题《leetcode--LCR 021.删除链表的倒数第N个结点》

https://leetcode.cn/problems/SLwz0R/ 这道题我们可以设一个哨兵位&#xff0c;然后把要遍历链表的结点指向该哨兵位。最后用for循环将指针指向要删除结点的前一个。 struct ListNode* removeNthFromEnd(struct ListNode* head, int n){struct ListNode* dummy malloc(sizeof…