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. jar包读取配置文件

    读取jar包内配置文件: Properties config = new Properties(); InputStream in = this.getClass().getClassLoader() ...

  2. html的img标签

    html显示图片 1.最简单: <img src="图片路径"/> 2.如果要改变图片显示的尺寸 <img src="图片路径" width= ...

  3. whatwg-fetch

    fetch 是什么 XMLHttpRequest的最新替代技术 fetch优点 接口更简单.简洁,更加语义化 基于promise,更加好的流程化控制,可以不断then把参数传递,外加 async/aw ...

  4. div+css 让一个小div在另一个大div里面 垂直居中

    方法1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 .parent {           width:800px;           height:500px;       ...

  5. Ajax嵌套Ajax的模版

    引入 在开发中,难免会碰到需要发送两次ajax请求或者更多的情况 情境:我们需要resultB数据,后台提供的接口要先传入参数paramA,获取到resultA,然后resultA作为参数,调用另外一 ...

  6. jquery报表插件收藏 MARK

    Highcharts http://www.hcharts.cn/ 统计报表插件 jquery ui官网 http://jqueryui.com/selectmenu/#custom_render

  7. ajax返回整个页面

       

  8. IE11 F12 开发人员工具 查看 Cookie

    参考网址:Using the F12 developer tools in IE11 Step1 : IE11 => F12 打开 开发人员工具 Step2:开发人员工具 => 网络F5 ...

  9. 三:Springboot整合Redis

    一:springboot整合redis redis版本:3.0.0 运行环境:linux 1.安装redis 1.1安装gcc yum install gcc-c++ 1.2解压redis.3.0.0 ...

  10. jmeter简单使用示例

    1.下载后解压,运行bin目录下的jmeter.bat 2.add ThreadGroup 3.add request 4.add listener