commons.pool2 对象池的使用

commons.pool2 对象池的使用java

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


池对象工厂 PooledObjectFactory和池对象 DefaultPooledObject

先了解个概念:apache

池对象工厂(PooledObjectFactory接口):用来建立池对象, 将不用的池对象进行钝化(passivateObject), 对要使用的池对象进行激活(activeObject), 对池对象进行验证(validateObject), 对有问题的池对象进行销毁(destroyObject)等工做ide

PooledObjectFactory是一个池化对象工厂接口,定义了生成对象、激活对象、钝化对象、销毁对象的方法,以下spa

public interface PooledObjectFactory<T> {
    PooledObject<T> makeObject() throws Exception;

    void destroyObject(PooledObject<T> var1) throws Exception;

    boolean validateObject(PooledObject<T> var1);

    void activateObject(PooledObject<T> var1) throws Exception;

    void passivateObject(PooledObject<T> var1) throws Exception;
}

若是须要使用Commons-Pool,那么你就须要提供一个PooledObjectFactory接口的具体实现。一个比较简单的办法就是,继承BasePooledObjectFactory这个抽象类。而继承这个抽象类,只须要实现两个方法:create()和wrap(T obj)。code

实现create()方法很简单,而实现wrap(T obj)也有捷径,可使用类DefaultPooledObject,代码能够参考以下:xml

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

/**
 * Created by liyanxin on 2015/3/25.
 */
public class PooledStringBufferFactory extends BasePooledObjectFactory<StringBuffer> {

    @Override
    public StringBuffer create() throws Exception {
        return new StringBuffer(16);
    }

    @Override
    public PooledObject<StringBuffer> wrap(StringBuffer stringBuffer) {
        return new DefaultPooledObject<StringBuffer>(stringBuffer);
    }
}

固然还有其余的池对象工厂,如KeyedPooledObjectFactory,和PooledObjectFactory接口相似,只是在相关的方法中多了Key参数,以下,对象

public interface KeyedPooledObjectFactory<K,V> {
   
    PooledObject<V> makeObject(K key) throws Exception;
  
    void destroyObject(K key, PooledObject<V> p) throws Exception;

    boolean validateObject(K key, PooledObject<V> p);
   
    void activateObject(K key, PooledObject<V> p) throws Exception;

    void passivateObject(K key, PooledObject<V> p) throws Exception;
}


建立对象池 GenericObjectPool

在org.apache.commons.pool2.impl中预设了三个能够直接使用的对象池:GenericObjectPool、GenericKeyedObjectPool和SoftReferenceObjectPool。继承

一般使用GenericObjectPool来建立对象池,若是是对象池是Keyed的,那么可使用GenericKeyedObjectPool来建立对象池。这两个类都提供了丰富的配置选项。这两个对象池的特色是能够设置对象池中的对象特征,包括LIFO(后进先出)方式、最大空闲数、最小空闲数、是否有效性检查等等。二者的区别如前面所述,后者支持Keyed。接口

而SoftReferenceObjectPool对象池,它利用一个java.util.ArrayList对象来保存对象池里的对象。不过它并不在对象池里直接保存对象自己,而是保存它们的“软引用”队列

(Soft Reference)。这种对象池的特点是:能够保存任意多个对象,不会有容量已满的状况发生;在对象池已空的时候,调用它的borrowObject方法,会自动返回新建立的实例;能够在初始化同时,在池内预先建立必定量的对象;当内存不足的时候,池中的对象能够被Java虚拟机回收。

举个例子:

new GenericObjectPool<StringBuffer>(new PooledStringBufferFactory());

咱们也可使用GenericObjectPoolConfig来对上面建立的对象池进行一些参数配置,建立的Config参数,可使用setConfig方法传给对象池,也能够在对象池的构造方法中做为参数传入。

举个例子:

GenericObjectPoolConfig conf = new GenericObjectPoolConfig();
conf.setMaxTotal(20);
conf.setMaxIdle(10);
...
GenericObjectPool<StringBuffer> pool = new GenericObjectPool<StringBuffer>(new PooledStringBufferFactory(), conf);


使用对象池

对象池使用起来很方便,简单一点就是使用borrowObject和returnObject两个方法,直接给参考代码吧:

borrowObject部分代码,具体请看源码:借出池对象,经过新建create()或从idleObjects双端队列中返回池对象。idleObjects是一个双端队列,保存返回对象池的对象,下次用的时候按照LIFO的原则(或其余原则)借出对象。

public T borrowObject(long borrowMaxWaitMillis) throws Exception {
    PooledObject<T> p = null;

    while (p == null) {
        create = false;
        if (blockWhenExhausted) {
            p = idleObjects.pollFirst();
            if (p == null) {
                p = create();
                if (p != null) {
                    create = true;
                }
            }
            if (p == null) {
                if (borrowMaxWaitMillis < 0) {
                    p = idleObjects.takeFirst();
                } else {
                    p = idleObjects.pollFirst(borrowMaxWaitMillis,
                            TimeUnit.MILLISECONDS);
                }
            }
            if (p == null) {
                throw new NoSuchElementException(
                        "Timeout waiting for idle object");
            }
            if (!p.allocate()) {
                p = null;
            }
        } else {
            p = idleObjects.pollFirst();
            if (p == null) {
                p = create();
                if (p != null) {
                    create = true;
                }
            }
        }
    }
    return p.getObject();
}

returnObject方法,部分代码,具体请看源码:返回池对象,放入idleObjects双端队列保存。

关键代码:

public void returnObject(T obj) {
    PooledObject<T> p = allObjects.get(obj);

    int maxIdleSave = getMaxIdle();
    if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
        try {
            destroy(p);
        } catch (Exception e) {
            swallowException(e);
        }
    } else {
        if (getLifo()) {
            idleObjects.addFirst(p);
        } else {
            idleObjects.addLast(p);
        }
    }
    updateStatsReturn(activeTime);
}

这只是大致上的逻辑,还有更多的细节逻辑控制。好比何时销毁,何时建立等等。

==============END==============

相关文章
相关标签/搜索