commons.pool2 对象池的使用

1
2
3
4
5
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.3</version>
</dependency>

池对象工厂 PooledObjectFactory和池对象 DefaultPooledObject

先了解个概念:

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

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

1
2
3
4
5
6
7
8
9
10
11
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)。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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参数,如下,

1
2
3
4
5
6
7
8
9
10
11
12
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虚拟机回收。

举个例子:

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

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

举个例子:

1
2
3
4
5
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的原则(或其他原则)借出对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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双端队列保存。

关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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==============

commons.pool2 对象池的使用的更多相关文章

  1. JedisCluster中应用的Apache Commons Pool对象池技术

    对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分.   apache common pool 官方文档可以参考:https://c ...

  2. Apache common pool2 对象池

    对象池的容器:包含一个指定数量的对象.从池中取出一个对象时,它就不存在池中,直到它被放回.在池中的对象有生命周期:创建,验证,销毁,对象池有助于更好地管理可用资源,防止JVM内部大量临时小对象,频繁触 ...

  3. 缓冲&缓存&对象池概念的理解

    一).缓冲 作用:缓解程序上下层之间的性能差异. 1).当上层组件的性能优于下层组件时加入缓冲机制可以减少上层组件对下 层组件的等待时间. 2).上层组件不需要等待下层组件接收全部数据,即可返回操作, ...

  4. Java--对象池化技术 org.apache.commons.pool2.ObjectPool

    org.apache.commons.pool2.ObjectPool提供了对象池,开发的小伙伴们可以直接使用来构建一个对象池 使用该对象池具有两个简单的步骤: 1.创建对象工厂,org.apache ...

  5. 对象池化技术 org.apache.commons.pool

    恰当地使用对象池化技术,可以有效地减少对象生成和初始化时的消耗,提高系统的运行效率.Jakarta Commons Pool组件提供了一整套用于实现对象池化的框架,以及若干种各具特色的对象池实现,可以 ...

  6. Lettuce连接池——解决“MXBean already registered with name org.apache.commons.pool2:type=GenericObjectPool,name=pool”

    LettuceConfig: package com.youdao.outfox.interflow.config; import io.lettuce.core.support.Connection ...

  7. Apache Common-pool2对象池分析和应用

    Apache Common-pool2包提供了一个通用的对象池技术的实现.可以很方便的基于它来实现自己的对象池,比如DBCP和Jedis他们的内部对象池的实现就是依赖于Common-pool2. 对象 ...

  8. Apache Commons Pool2 源码分析 | Apache Commons Pool2 Source Code Analysis

    Apache Commons Pool实现了对象池的功能.定义了对象的生成.销毁.激活.钝化等操作及其状态转换,并提供几个默认的对象池实现.在讲述其实现原理前,先提一下其中有几个重要的对象: Pool ...

  9. java对象池commons-pool-1.6详解(一)

    自己的项目中用到了 对象池 commons-pool: package com.sankuai.qcs.regulation.protocol.client; import com.dianping. ...

随机推荐

  1. vue 坑之 vuex requires a Promise polyfill in this browser

    android内嵌H5页面不显示出现这个问题,原因有很多 首先,别急,请看下面的推荐方案: 1.找个Android真机测试下(机型版本为4.4以上),真机联调测试 Android 只需要四个步骤: 1 ...

  2. android去除标题栏

    在 AndroidManifast.xml 文件中 将 theme="@style/AppTheme" 改为 theme="@style/Theme.AppCompat. ...

  3. 解决WORD2013输入时光标老跳的问题

    Word2013有一个非常影响使用的bug.就是在编辑文档时,光标会乱跑,影响输入.微软给出了一个kb2863845 160多MB的补丁包,安装完成后就可以解决这个问题.  补丁下载链接: 链接:ht ...

  4. PS基础,英语

    PS基础(矢量图案的绘制) 水平参考线:新建背景(长宽一致,背景内容为透明)---设置水平参考线(水平垂直都要)---完成. 背景制作:设置前景色---用矩形选框工具绘制正方形选区(背景已被参考线平分 ...

  5. JQuery对数组的一些操作总结

    JQuery对数组的处理非常便捷并且功能强大齐全,一步到位的封装了很多原生js数组不能企及的功能.下面来看看JQuery数组的强大之处在哪. $.each(array, [callback]) 遍历 ...

  6. ajax返回整个页面

       

  7. golang学习之interface与其它类型转换

    如下函数,将interface变量in转换为int: func formatTimeStamp(in interface{}, layout string) (out string) { timeSt ...

  8. cygwin 的安装和配置

         Cygwin是一个在windows平台上运行的类UNIX模拟环境,是cygnus solutions公司开发的自由软件(该公司开发的著名工具还有eCos,不过现已被Redhat收购).它对于 ...

  9. Windows下RSA密钥生成工具openssl

    下载openssl.zip 1. 生成原始 RSA私钥文件 private_key.pem openssl genrsa -out private_key.pem 1024 2. 将原始 RSA私钥转 ...

  10. IntelliJ IDEA 16创建Web项目

    首先要理解一个概念:在IntelliJ IDEA中“new Project”相当于eclipse中的工作空间(Workspace),而“new Module”相当于eclipse中的工程(Projec ...