commons-pool2自定义对象池使用

commons-pool2自定义对象池使用

文章目录

  • commons-pool2自定义对象池使用
      • 一、简介
      • 二、准备
        • 2.1 官网地址
        • 2.2 maven依赖包
      • 三、commons-pool2池的关键方法和类
        • 2.1 关键类和方法
          • 2.1.1 池化对象工厂类
          • 2.1.2 默认池化对象包装类
          • 2.1.3 对象池类
          • 2.1.4 对象池控制类
        • 2.2 线程安全
      • 四、使用
        • 4.1 创建对象类
        • 4.2 创建池化对象工厂类
        • 4.3 创建对象池类
        • 4.4 创建对象池配置
        • 4.5 测试
      • 五、结尾

一、简介

在java开发中,为了减少对象创建和销毁的开销,我们常常复用对象,如单例模式。在同时需要多个对象时,则采用池,如线程池、数据库连接池等。这里介绍基于apache的commons-pool2包来创建自定义的对象池。

二、准备

2.1 官网地址

官网地址:http://commons.apache.org/proper/commons-pool/

2.2 maven依赖包


  org.apache.commons
  commons-pool2
  2.4.2

三、commons-pool2池的关键方法和类

2.1 关键类和方法

2.1.1 池化对象工厂类

org.apache.commons.pool2.PooledObjectFactory,用于对象的创建、激活、钝化、销毁等操作。

2.1.2 默认池化对象包装类

org.apache.commons.pool2.impl.DefaultPooledObject,对实际对象进行包装,添加如状态等信息。

2.1.3 对象池类

org.apache.commons.pool2.impl.GenericObjectPool,对象池。

2.1.4 对象池控制类

org.apache.commons.pool2.impl.GenericObjectPoolConfig,用于控制如最大连接数,最大空闲数、最小空闲数等。

2.2 线程安全

commons-pool2包的对象池是线程安全的。
所有对象存在ConcurrentHashMap中;
空闲对象存在LinkedBlockingDeque中。位org.apache.commons.pool2.impl.GenericObjectPool类中的关键源码如下:

// --- configuration attributes --------------------------------------------
private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
private final PooledObjectFactory<T> factory;
// --- internal attributes -------------------------------------------------
/*
 * All of the objects currently associated with this pool in any state. It
 * excludes objects that have been destroyed. The size of
 * {@link #allObjects} will always be less than or equal to {@link
 * #_maxActive}. Map keys are pooled objects, values are the PooledObject
 * wrappers used internally by the pool.
 */
private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =
    new ConcurrentHashMap<IdentityWrapper<T>, PooledObject<T>>();
/*
 * The combined count of the currently created objects and those in the
 * process of being created. Under load, it may exceed {@link #_maxActive}
 * if multiple threads try and create a new object at the same time but
 * {@link #create()} will ensure that there are never more than
 * {@link #_maxActive} objects created at any one time.
 */
private final AtomicLong createCount = new AtomicLong(0);
private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
// JMX specific attributes
private static final String ONAME_BASE =
    "org.apache.commons.pool2:type=GenericObjectPool,name=";
// Additional configuration properties for abandoned object tracking
private volatile AbandonedConfig abandonedConfig = null;

四、使用

4.1 创建对象类

这里创建示例对象Link,如下:

/**
 * 池中的对象(示例)
 */
@Data
static class Link {
    private String url;

    public Link(String url) {
        this.url = url;
    }
}

4.2 创建池化对象工厂类

实现接口PooledObjectFactory,接口包含对象创建、激活、钝化、销毁、验证对象是否安全等方法,示例如下:

/**
 * 池对象工厂,对对象的操作
 */
static class LinkPooledObjectFactory implements PooledObjectFactory<Link> {
    private String url;

    public LinkPooledObjectFactory() {
    }

    public LinkPooledObjectFactory(String url) {
        this.url = url;
    }

    /**
     * 当需要新对象时调用,创建对象
     *
     * @return
     * @throws Exception
     */
    @Override
    public PooledObject<Link> makeObject() throws Exception {
        System.out.println("makeObject");
        Link o = new Link(url);
        //用DefaultPooledObject包裹创建的对象,用于跟踪对象的状态
        return new DefaultPooledObject<>(o);
    }

    /**
     * 不再需要对象时调用,销毁对象
     *
     * @param p
     * @throws Exception
     */
    @Override
    public void destroyObject(PooledObject<Link> p) throws Exception {
        System.out.println("destroyObject");
        Link o = p.getObject();
        o = null;
    }


    /**
     * 从池中取对象或归还对象到池中时,判断对象安全
     *
     * @param p
     * @return
     */
    @Override
    public boolean validateObject(PooledObject<Link> p) {
        System.out.println("validateObject");
        return false;
    }

    /**
     * 从池中取出对象,使用前,再次初始化对象
     *
     * @param p
     * @throws Exception
     */
    @Override
    public void activateObject(PooledObject<Link> p) throws Exception {
        System.out.println("activateObject");
    }

    /**
     * 当对象返回到空闲池时调用,钝化对象
     *
     * @param p
     * @throws Exception
     */
    @Override
    public void passivateObject(PooledObject<Link> p) throws Exception {
        System.out.println("passivateObject");
    }
}

4.3 创建对象池类

实现接口GenericObjectPool, 示例如下:

/**
 * 对象池
 */
static class LinkPool extends GenericObjectPool<Link> {

    public LinkPool(PooledObjectFactory<Link> factory) {
        super(factory);
    }

    public LinkPool(PooledObjectFactory<Link> factory, GenericObjectPoolConfig config) {
        super(factory, config);
    }

    public LinkPool(PooledObjectFactory<Link> factory, GenericObjectPoolConfig config, AbandonedConfig abandonedConfig) {
        super(factory, config, abandonedConfig);
    }
}

4.4 创建对象池配置

对象池配置,包含最大对象数、最大空闲对象数、最小空闲对象数等配置,示例如下:

//创建对象池配置
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
//最大连接数
config.setMaxTotal(6);
//最大空闲数
config.setMaxIdle(3);
//最小空闲数
config.setMinIdle(1);
//最长等待时间,3秒
config.setMaxWaitMillis(3000);

4.5 测试

public static void main(String[] args) throws Exception {
    //创建对象池配置
    GenericObjectPoolConfig config = new GenericObjectPoolConfig();
    //最大连接数
    config.setMaxTotal(6);
    //最大空闲数
    config.setMaxIdle(3);
    //最小空闲数
    config.setMinIdle(1);
    //最长等待时间,3秒
    config.setMaxWaitMillis(3000);

    //创建对象池工厂
    LinkPooledObjectFactory factory = new LinkPooledObjectFactory("hehe");

    //创建对象池
    LinkPool pool = new LinkPool(factory, config);

    //测试
    for (int i = 0; i < 8 ; i++) {
        //获取对象
        Link link = pool.borrowObject();
        System.out.println(link);
        TimeUnit.SECONDS.sleep(1);
        //使用后归还对象
        pool.returnObject(link);
    }
}

五、结尾

上面列出了基于commons-pools中的使用,更多操作可查看源码。

你可能感兴趣的:(java)