commons.pool2 对象池的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangguosb/article/details/85930381

maven依赖

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

核心元素

  • PooledObjectFactory: 定义池化对象如何被创建、销毁及初始化等行为;
  • GenericObjectPool:对象池,管理池中的对象;

对象的生命周期

在这里插入图片描述

对象池配置说明GenericObjectPoolConfig

  • maxActive: 链接池中最大连接数,默认为8;
  • maxIdle: 链接池中最大空闲的连接数,默认为8;
  • minIdle: 连接池中最少空闲的连接数,默认为0;
  • maxWait: 当连接池资源耗尽时,调用者最大阻塞的时间,超时将跑出异常。单位,毫秒数;默认为-1.表示永不超时;
  • minEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲连接将可能会被移除,负值(-1)表示不移除;
  • softMinEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲链接将会被移除,且保留“minIdle”个空闲连接数,默认为-1;
  • numTestsPerEvictionRun: 对于“空闲链接”检测线程而言,每次检测的链接资源的个数,默认为3;
  • testOnBorrow: 向调用者输出“链接”资源时,是否检测是有有效,如果无效则从连接池中移除,并尝试获取继续获取。默认为false。建议保持默认值;
  • testOnReturn: 向连接池“归还”链接时,是否检测“链接”对象的有效性。默认为false,建议保持默认值;
  • testWhileIdle: 向调用者输出“链接”对象时,是否检测它的空闲超时;默认为false。如果“链接”空闲超时,将会被移除。建议保持默认值;
  • timeBetweenEvictionRunsMillis: “空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”,默认为-1;
  • whenExhaustedAction: 当“连接池”中active数量达到阀值时,即“链接”资源耗尽时,连接池需要采取的手段, 默认为1:
    -> 0 : 抛出异常,
    -> 1 : 阻塞,直到有可用链接资源
    -> 2 : 强制创建新的链接资源

PoolableObjectFactory接口说明

  • makeObject() : 创建一个新对象。当对象池中的对象个数不足时,将会使用此方法来"输出"一个新的"对象",并交付给对象池管理;
  • destroyObject(Object obj) : 销毁对象。如果对象池中检测到某个"对象"idle的时间超时,或者操作者向对象池"归还对象"时检测到"对象"已经无效,那么此时将会导致"对象销毁";
  • activateObject(Object obj) : “激活"对象。当从Pool中获取一个对象交付给调用者使用前,会进行额外的"激活"操作,比如可以在activateObject方法中"重置"参数列表让调用者使用时感觉像一个"新创建"的对象一样;如果object是一个线程,可以在"激活"操作中重置"线程中断标记”,或者让线程从阻塞中唤醒等;如果 object是一个socket,那么可以在"激活操作"中刷新通道,或者对socket进行链接重建(假如socket意外关闭)等;
  • passivateObject(Object obj) : “钝化"对象。当调用者"归还对象"时,Pool将会"钝化对象”;钝化的言外之意,就是此"对象"暂且需要"休息"一下.如果object是一个 socket,那么可以passivateObject中清除buffer,将socket阻塞;需要注意的时,activateObject和passivateObject两个方法需要对应,避免死锁或者"对象"状态的混乱;

BasePooledObjectFactory类提供了基本实现;

使用样例

@Component
public class HDFSClientPool implements InitializingBean{

    private static final Logger LOGGER = LoggerFactory.getLogger(HDFSClientPool.class);

    @Value("${upload.hadoop.user.name}")
    private String hadoopUserName;

    @Value("${upload.hadoop.password}")
    private String hadoopPwd;

    private GenericObjectPool<HDFSClient> pool;

    @Override
    public void afterPropertiesSet() throws Exception {
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(10);
        poolConfig.setMaxTotal(10);
        poolConfig.setMinIdle(1);
        poolConfig.setMaxWaitMillis(30000);
        poolConfig.setMinEvictableIdleTimeMillis(300000);
        pool = new GenericObjectPool(new HDFSClientFactory(hadoopUserName, hadoopPwd), poolConfig);
        LOGGER.error(">>>>>>> GenericObjectPool: " + pool);
    }

    public HDFSClient getHDFSClient() throws Exception {
        return pool.borrowObject();
    }

    public void returnHDFSClient(HDFSClient client){
         pool.returnObject(client);
    }

    public void printActiveNum(){
        LOGGER.info("Active Num " + pool.getNumActive() + " " + pool.getNumIdle());
    }

}
public class HDFSClientFactory extends BasePooledObjectFactory<HDFSClient> {

    private static final Logger LOGGER = LoggerFactory.getLogger(HDFSClientFactory.class);

    private String hadoopUserName;

    private String hadoopPwd;

    public HDFSClientFactory(){}

    public HDFSClientFactory(String hadoopUserName, String hadoopPwd){
        this.hadoopUserName = hadoopUserName;
        this.hadoopPwd = hadoopPwd;
    }

    @Override
    public HDFSClient create() throws Exception {
        LOGGER.error("current thread create: " + Thread.currentThread().getName());
        return new HDFSClient(null, hadoopUserName, hadoopPwd);
    }

    @Override
    public PooledObject<HDFSClient> wrap(HDFSClient hdfsClient) {
        return new DefaultPooledObject<>(hdfsClient);
    }

    @Override
    public void destroyObject(PooledObject<HDFSClient> p) throws Exception {
        LOGGER.error("current thread destroy: " + Thread.currentThread().getName());
        if(p != null && p.getObject() != null){
            try{
                p.getObject().close();
                LOGGER.info("PooledObject destroy");
            }catch (Exception e){
                LOGGER.error("PooledObject destroy exception", e);
            }
        }
    }
}

参考:

  1. 参数说明:http://www.open-open.com/lib/view/open1415453575730.html
  2. https://blog.csdn.net/xlxxcc/article/details/52402931

猜你喜欢

转载自blog.csdn.net/yangguosb/article/details/85930381
今日推荐