# object-pool **Repository Path**: itxiaomi/object-pool ## Basic Information - **Project Name**: object-pool - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-11-27 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # springboot使用commons-pool2实现对象池 ## 一. 连接池概述 频繁的创建和销毁,会极大的降低系统的性能,而对象池会在初始化的时候会创建一定数量的对象,每次访问只需从对象池中获取对象,使用完毕后再放回对象池,并不是直接销毁,这样可以保证程序重复使用同一个对象而不需要每次访问都创建和销毁对象, 从而提高系统性能。 ## 二. commons-pool2介绍 #### 加入pool2依赖: ```xml org.apache.commons commons-pool2 2.6.2 ``` #### pool2的组成 ``` PooledObject(池化对象) PooledObjectFactory(对象工厂) ObjectPool (对象池) ``` #### 需要池化的对象 ```java /** * 需要池化的对象 * * @author lz * @date 2019/7/30 */ public class TestObject { private String name; private boolean isActive; public TestObject() { } public TestObject(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isActive() { return isActive; } public void setActive(boolean active) { isActive = active; } public void destroy(){ } } ``` #### TestObject 工厂 在commons-pool2中有两种工厂:PooledObjectFactory 和KeyedPooledObjectFactory,我们使用前者。 ```java public interface PooledObjectFactory { //创建对象 PooledObject makeObject(); //激活对象 void activateObject(PooledObject obj); //钝化对象 void passivateObject(PooledObject obj); //验证对象 boolean validateObject(PooledObject obj); //销毁对象 void destroyObject(PooledObject obj); } ``` 创建TestObjectFactory只需要继承BasePooledObjectFactory这个抽象类 ,而它则实现了PooledObjectFactory,也可以直接实现PooledObjectFactory接口;我们使用实现PooledObjectFactory接口: ```java import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; /** * TestObject 工厂类 * * @author lz * @date 2019/7/30 */ public class TestObjectFactory implements PooledObjectFactory { /** * /构造一个封装对象 * * @return * @throws Exception */ @Override public PooledObject makeObject() throws Exception { return new DefaultPooledObject<>(new TestObject()); } /** * 销毁对象 * * @param p * @throws Exception */ @Override public void destroyObject(PooledObject p) throws Exception { p.getObject().destroy(); } /** * 验证对象是否可用 * * @param p * @return */ @Override public boolean validateObject(PooledObject p) { return p.getObject().isActive(); } /** * 激活一个对象,使其可用用 * * @param p * @throws Exception */ @Override public void activateObject(PooledObject p) throws Exception { p.getObject().setActive(true); } /** * 钝化一个对象,也可以理解为反初始化 * * @param p * @throws Exception */ @Override public void passivateObject(PooledObject p) throws Exception { } } ``` #### 创建一个对象池 ```java import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.AbandonedConfig; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; /** * 自定义对象池 * * @author lz * @date 2019/7/30 */ public class TestObjectPool extends GenericObjectPool { public TestObjectPool(PooledObjectFactory factory) { super(factory); } public TestObjectPool(PooledObjectFactory factory, GenericObjectPoolConfig config) { super(factory, config); } public TestObjectPool(PooledObjectFactory factory, GenericObjectPoolConfig config, AbandonedConfig abandonedConfig) { super(factory, config, abandonedConfig); } } ``` ### spring 部分 #### 创建对象池配置类 ```java import org.springframework.boot.context.properties.ConfigurationProperties; /** * 对象池配置 * * @author lz * @date 2019/7/30 */ @ConfigurationProperties(prefix = PoolProperties.PROJECT_PREFIX) public class PoolProperties { public static final String PROJECT_PREFIX = "project.object"; /** * 最大空闲 */ private int maxIdle = 5; /** * 最大总数 */ private int maxTotal = 20; /** * 最小空闲 */ private int minIdle = 2; /** * 初始化连接数 */ private int initialSize = 3; public int getMaxIdle() { return maxIdle; } public void setMaxIdle(int maxIdle) { this.maxIdle = maxIdle; } public int getMaxTotal() { return maxTotal; } public void setMaxTotal(int maxTotal) { this.maxTotal = maxTotal; } public int getMinIdle() { return minIdle; } public void setMinIdle(int minIdle) { this.minIdle = minIdle; } public int getInitialSize() { return initialSize; } public void setInitialSize(int initialSize) { this.initialSize = initialSize; } } ``` 创建自动配置类 ```java import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.PreDestroy; /** * 对象池自动装配 * * @author lz * @date 2019/7/30 */ @EnableConfigurationProperties(PoolProperties.class) @Configuration public class PoolAutoConfiguration { private final PoolProperties poolProperties; private TestObjectPool pool; @Autowired public PoolAutoConfiguration(PoolProperties poolProperties) { this.poolProperties = poolProperties; } @ConditionalOnClass({TestObjectFactory.class}) @Bean protected TestObjectPool faceSDKPool() { TestObjectFactory faceSDKFactory = new TestObjectFactory(); //设置对象池的相关参数 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxIdle(poolProperties.getMaxIdle()); poolConfig.setMaxTotal(poolProperties.getMaxTotal()); poolConfig.setMinIdle(poolProperties.getMinIdle()); poolConfig.setBlockWhenExhausted(true); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); poolConfig.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30); //一定要关闭jmx,不然springboot启动会报已经注册了某个jmx的错误 poolConfig.setJmxEnabled(false); //新建一个对象池,传入对象工厂和配置 pool = new TestObjectPool(faceSDKFactory, poolConfig); initPool(poolProperties.getInitialSize(), poolProperties.getMaxIdle()); return pool; } /** * 预先加载testObject对象到对象池中 * * @param initialSize 初始化连接数 * @param maxIdle 最大空闲连接数 */ private void initPool(int initialSize, int maxIdle) { if (initialSize <= 0) { return; } int size = Math.min(initialSize, maxIdle); for (int i = 0; i < size; i++) { try { pool.addObject(); } catch (Exception e) { throw new RuntimeException(e); } } } @PreDestroy public void destroy() { if (pool != null) { pool.close(); } } } ``` 使用 ```java @Autowired private TestObjectPool testObjectPool; public void test() { TestObject testObject = null; try { testObject = testObjectPool.borrowObject(); //省略业务代码... } catch (Exception e) { e.printStackTrace(); } finally { if (testObject != null) { //最终归还对象到对象池 testObjectPool.returnObject(testObject); } } } ``` ## 三.对象池的相关参数说明 ### **lifo** ``` 提供了后进先出(LIFO)与先进先出(FIFO)两种行为模式的池; 默认 DEFAULT_LIFO = true, 当池中有空闲可用的对象时,调用borrowObject方法会返回最近(后进)的实例。 ``` ### **fairness** ``` 当从池中获取资源或者将资源还回池中时,是否使用;java.util.concurrent.locks.ReentrantLock.ReentrantLock 的公平锁机制。 默认DEFAULT_FAIRNESS = false ``` ### **maxWaitMillis** ``` 当连接池资源用尽后,调用者获取连接时的最大等待时间(单位 :毫秒); 默认值 DEFAULT_MAX_WAIT_MILLIS = -1L, 永不超时。 ``` ### **minEvictableIdleTimeMillis** ``` 连接的最小空闲时间,达到此值后该空闲连接可能会被移除(还需看是否已达最大空闲连接数); 默认值 DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L ``` ### **evictorShutdownTimeoutMillis** ``` 关闭驱逐线程的超时时间; 默认值 DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS = 10L * 1000L ``` ### **softMinEvictableIdleTimeMillis** ``` 连接空闲的最小时间,达到此值后空闲链接将会被移除,且保留minIdle个空闲连接数; 默认值 DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1 ``` ### **numTestsPerEvictionRun** ``` 检测空闲对象线程每次运行时检测的空闲对象的数量; 如果 numTestsPerEvictionRun>=0, 则取numTestsPerEvictionRun 和池内的连接数 的较小值 作为每次检测的连接数; 如果 numTestsPerEvictionRun<0,则每次检查的连接数是检查时池内连接的总数除以这个值的绝对值再向上取整的结果; 默认值 DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3 ``` ### **evictionPolicyClassName** ``` 驱逐策略的类名; 默认值 DEFAULT_EVICTION_POLICY_CLASS_NAME = “org.apache.commons.pool2.impl.DefaultEvictionPolicy” ``` ### **testOnCreate** ``` 在创建对象时检测对象是否有效(true : 是) , 配置true会降低性能; 默认值 DEFAULT_TEST_ON_CREATE = false ``` ### **testOnBorrow** ``` 在从对象池获取对象时是否检测对象有效(true : 是) , 配置true会降低性能; 默认值 DEFAULT_TEST_ON_BORROW = false ``` ### **testOnReturn** ``` 在向对象池中归还对象时是否检测对象有效(true : 是) , 配置true会降低性能; 默认值 DEFAULT_TEST_ON_RETURN = false ``` ### **testWhileIdle** ``` 在检测空闲对象线程检测到对象不需要移除时,是否检测对象的有效性。建议配置为true,不影响性能,并且保证安全性; 默认值 DEFAULT_TEST_WHILE_IDLE = false ``` ### **timeBetweenEvictionRunsMillis** ``` 空闲连接检测的周期(单位毫秒);如果为负值,表示不运行检测线程; 默认值 DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L ``` ### **blockWhenExhausted** ``` 当对象池没有空闲对象时,新的获取对象的请求是否阻塞(true 阻塞,maxWaitMillis 才生效; false 连接池没有资源立马抛异常) 默认值 DEFAULT_BLOCK_WHEN_EXHAUSTED = true ``` ### **jmxEnabled** ``` 是否注册JMX 默认值 DEFAULT_JMX_ENABLE = true ``` ### **jmxNamePrefix** ``` JMX前缀 默认值 DEFAULT_JMX_NAME_PREFIX = “pool” ``` ### **jmxNameBase** ``` 使用 base + jmxNamePrefix + i 来生成ObjectName 默认值 DEFAULT_JMX_NAME_BASE = null,GenericObjectPool 构造方法使用 ONAME_BASE 初始化。 ``` ### **maxTotal** ``` 最大连接数,默认值 DEFAULT_MAX_TOTAL = 8 ``` ### **maxIdle** ``` 最大空闲连接数, 默认值 DEFAULT_MAX_IDLE = 8 ``` ### **minIdle** ``` 最小空闲连接数, 默认值 DEFAULT_MIN_IDLE = 0 ```