Java BasePooledObjectFactory 对象池化技术

java,basepooledobjectfactory,对象,技术 · 浏览次数 : 133

小编点评

**Java GenericObjectPool 对象池化技术** **简介** Java GenericObjectPool 是一个用于管理已经初始化过且可以使用的对象池。它可以用于在需要时创建和销毁对象,并提供对对象的管理和监控功能。 **主要功能** * 创建和销毁对象。 * 获取和归还对象。 * 校验对象是否可用。 * 激活钝化对象。 **使用** 1. 创建一个 `MqttConnectionFactory` 对象。 2. 创建一个 `GenericObjectPoolConfig` 对象,指定对象池的属性,例如最大线程数量。 3. 创建一个 `GenericObjectPool` 对象,使用工厂创建对象池。 4. 从对象池中获取或归还对象。 5. 监控对象池的空闲状态。 **示例** ```java // 创建对象池工厂 MqttConnectionFactory personPoolFactory = new MqttConnectionFactory(); // 创建对象池配置 GenericObjectPoolConfig<MqttConnection> objectPoolConfig = new GenericObjectPoolConfig<>(); objectPoolConfig.setMaxTotal(50); // 创建对象池 GenericObjectPool<MqttConnection> mqttPool = new GenericObjectPool<>(personPoolFactory, objectPoolConfig); // 获取对象 MqttConnection mqtt = mqttPool.borrowObject(); // 执行任务 mqtt.publish("Id:\" + count + \" Time: \" + DateUtil.now()); // 归还对象 mqttPool.returnObject(mqtt); ``` **优点** * 降低内存使用量。 * 提高性能。 * 提供对对象的管理和监控功能。 **缺点** * 创建和销毁对象可能需要一些时间。 * 对象池可能在空闲状态时存在性能问题。

正文

Java GenericObjectPool 对象池化技术--SpringBoot sftp 连接池工具类

一个对象池包含一组已经初始化过且可以使用的对象,而可以在有需求时创建和销毁对象。池的用户可以从池子中取得对象,对其进行操作处理,并在不需要时归还给池子而非直接销毁它。这是一种特殊的工厂对象。

点击查看 MQTT(EMQX) - SpringBoot 创建 mqtt 连接池
点击查看 MQTT(EMQX) - SpringBoot 整合MQTT Demo - 附源代码

BasePooledObjectFactory 对象池化技术 的使用
image

Pom.xml

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

MqttConnection.java

package com.vipsoft.mqtt.pool;
 
public class MqttConnection {

    private String mqttClient;
    ;

    public MqttConnection(String mqttClient) {
        this.mqttClient = mqttClient;
    }

    public String getMqttClient() {
        return mqttClient;
    }

    public void setMqttClient(String mqttClient) {
        this.mqttClient = mqttClient;
    }

    /**
     * 推送方法消息
     */
    public void publish(String msg) throws Exception {
        System.out.println("对象" + mqttClient + ":" + "执行任务" + msg);
    }

    @Override
    public String toString() {
        return "MqttConnection{" + "id=" + mqttClient + '}';
    }

}

MqttConnectionFactory.java

package com.vipsoft.mqtt.pool;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicInteger;

public class MqttConnectionFactory extends BasePooledObjectFactory<MqttConnection> {

    private static final Logger logger = LoggerFactory.getLogger(MqttConnectionFactory.class);


    // AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减
    private AtomicInteger counter = new AtomicInteger();

    /**
     * 在对象池中创建对象
     *
     * @return
     * @throws Exception
     */
    @Override
    public MqttConnection create() throws Exception {

        // 实现线程安全避免在高并发的场景下出现clientId重复导致无法创建连接的情况
        int count = this.counter.addAndGet(1);
        MqttConnection mqttConnection = new MqttConnection("MqttConnection:" + count);
        logger.info("在对象池中创建对象 {}", mqttConnection.toString());
        return mqttConnection;
    }

    /**
     * common-pool2 中创建了 DefaultPooledObject 对象对对象池中对象进行的包装。
     * 将我们自定义的对象放置到这个包装中,工具会统计对象的状态、创建时间、更新时间、返回时间、出借时间、使用时间等等信息进行统计
     *
     * @param mqttConnection
     * @return
     */
    @Override
    public PooledObject<MqttConnection> wrap(MqttConnection mqttConnection) {
        logger.info("封装默认返回类型 {}", mqttConnection.toString());
        return new DefaultPooledObject<>(mqttConnection);
    }

    /**
     * 销毁对象
     *
     * @param p 对象池
     * @throws Exception 异常
     */
    @Override
    public void destroyObject(PooledObject<MqttConnection> p) throws Exception {
        logger.info("销毁对象 {}", p.getObject().getMqttClient());
        super.destroyObject(p);
    }

    /**
     * 校验对象是否可用
     *
     * @param p 对象池
     * @return 对象是否可用结果,boolean
     */
    @Override
    public boolean validateObject(PooledObject<MqttConnection> p) {
        logger.info("校验对象是否可用 {}", p.getObject().getMqttClient());
        return super.validateObject(p);
    }

    /**
     * 激活钝化的对象系列操作
     *
     * @param p 对象池
     * @throws Exception 异常信息
     */
    @Override
    public void activateObject(PooledObject<MqttConnection> p) throws Exception {
        logger.info("激活钝化的对象 {}", p.getObject().getMqttClient());
        super.activateObject(p);
    }

    /**
     * 钝化未使用的对象
     *
     * @param p 对象池
     * @throws Exception 异常信息
     */
    @Override
    public void passivateObject(PooledObject<MqttConnection> p) throws Exception {
        logger.info("钝化未使用的对象 {}", p.getObject().getMqttClient());
        super.passivateObject(p);
    }
}

PoolTest.java

package com.vipsoft.mqtt;

import cn.hutool.core.date.DateUtil;
import com.vipsoft.mqtt.pool.MqttConnection;
import com.vipsoft.mqtt.pool.MqttConnectionFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

@SpringBootTest
public class PoolTest {

    @Test
    void basePooledTest() throws InterruptedException {

        AtomicInteger atomicInteger = new AtomicInteger();

        int excutorCount = 15;
        CountDownLatch countDownLatch = new CountDownLatch(excutorCount);

        // =====================创建线程池=====================
        ExecutorService excutor = Executors.newFixedThreadPool(5);
        // =====================创建对象池 项目中使用了InitializingBean.afterPropertiesSet() 中创建=====================
        // 对象池工厂
        MqttConnectionFactory personPoolFactory = new MqttConnectionFactory();
        // 对象池配置
        GenericObjectPoolConfig<MqttConnection> objectPoolConfig = new GenericObjectPoolConfig<>();
        objectPoolConfig.setMaxTotal(50);
        // 对象池
        GenericObjectPool<MqttConnection> mqttPool = new GenericObjectPool<>(personPoolFactory, objectPoolConfig);
        // =====================测试对象池=====================
        // 循环100次,从线程池中取多个多线程执行任务,来测试对象池
        for (int i = 0; i < excutorCount; i++) {
            excutor.submit(new Thread(() -> {
                // 模拟从对象池取出对象,执行任务
                MqttConnection mqtt = null;
                try {
                    // 从对象池取出对象
                    mqtt = mqttPool.borrowObject();
                    // 让对象工作
                    int count = atomicInteger.addAndGet(1);
                    mqtt.publish("Id:" + count + " Time: " + DateUtil.now());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 回收对象到对象池
                    if (mqtt != null) {
                        mqttPool.returnObject(mqtt);
                    }
                    countDownLatch.countDown();
                }
            }));
        }
        countDownLatch.await();
    }
}

image

与Java BasePooledObjectFactory 对象池化技术相似的内容:

Java BasePooledObjectFactory 对象池化技术

Java GenericObjectPool 对象池化技术--SpringBoot sftp 连接池工具类 一个对象池包含一组已经初始化过且可以使用的对象,而可以在有需求时创建和销毁对象。池的用户可以从池子中取得对象,对其进行操作处理,并在不需要时归还给池子而非直接销毁它。这是一种特殊的工厂对象。

Java GenericObjectPool 对象池化技术--SpringBoot sftp 连接池工具类

SpringBoot sftp 连接池工具类 使用`GenericObjectPool`只需要创建一个对象工厂类,继承`BasePooledObjectFactory`并重写它的`create()`和`destroyObject()`。Apache Commons Pool是一个对象池的框架,他提供了一整套用于实现对象池化的API。它提供了三种对象池:GenericKeyedObjectPool,

Java异步判断线程池所有任务是否执行完成的方法

本文详细介绍了Java异步判断线程池所有任务是否执行完成的方法,分别介绍了使用ExecutorService和CountDownLatch的方法示例、使用ExecutorService的invokeAll方法和Future列表的方法示例、使用ExecutorService来异步执行多个Callabl...

面试官:Java线程可以无限创建吗?

哈喽,大家好,我是世杰。 ⏩本次给大家介绍一下操作系统线程和Java的线程以及二者的关联 1. 面试连环call Java线程可以无限创建吗? Java线程和操作系统线程有什么关联? 操作系统为什么要区分内核态和用户态? ⏩要想解答这些问题,我们要先从操作系统线程开始说起,让我们开始吧�

Java 方法中循环调用具有事务的方法

本文简要介绍了Java 方法中循环调用具有事务的具体方法示例,虽然@Transactional是Spring中最常用和推荐的方式,但是本文还简要介绍了其他5种方法可以实现类似的功能。

Java基础:线程的三种创建方式

一、继承Thread类 定义一个类继承线程类Thread 重写run()方法 创建线程对象 调用线程对象的start()方法创建线程 Thread类的常用API setName(String name):给线程取名字 getName():获取线程的名字 public static Thread cu

面试官:Java类是如何被加载到内存中的?

面试连环call Java类是如何被加载到内存中的? Java类的生命周期都有哪些阶段? JVM加载的class文件都有哪些来源? JVM在加载class文件时,何时判断class文件的格式是否符合要求? 类生命周期 一个类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期将会经历加载、验

Java定时任务实现优惠码

在Java中实现定时任务来发放优惠码,我们可以使用多种方法,比如使用java.util.Timer类、ScheduledExecutorService接口,或者更高级的框架如Spring的@Scheduled注解。这里,我将以ScheduledExecutorService为例来展示如何实现这一功能

有手就会的 Java 处理压缩文件

@目录前言背景第一步:编写代码1.1 请求层1.2 业务处理层1.3 新增配置第二步:解压缩处理2.1 引入依赖2.2 解压缩工具类总结 前言 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i、 提示:以下是本篇文章正文内容,下面案例可供参考 背景 在项目出现上传文件,其中文件包含压缩包,并

【进阶篇】Java 项目中对使用递归的理解分享

笔者在最近的项目开发中,遇到了两个父子关系紧密相关的场景:评论树结构、部门树结构。具体的需求如:找出某条评论下的所有子评论id集合,找出某个部门下所有的子部门id集合。