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. Linux定时增量更新文件--转

    http://my.oschina.net/immk/blog/193926 动机与需求:现在有两台服务器A和B,由于A的存储随时会挂(某些原因),所以需要B机器上有A的备份,并且能够与A同步更新 一 ...

  2. Java中final修饰参数的作用

    在方法参数前面加final关键字就是为了防止数据在方法体中被修改. 主要分两种情况:第一,用final修饰基本数据类型:第二,用final修饰引用类型. 第一种情况,修饰基本类型(非引用类型).这时参 ...

  3. Spring mvc 中 DispatcherServlet 的学习和理解

    上图表示当客户请求来到时,spring架构作出响应的流程,可以从图中看到看到请求分发的中心就是 DispatcherServlet 类,DispatcherServlet的任务是将请求发送给Sprin ...

  4. log4js日志

    安装log4js:npm install log4js express中配置log4js中间件: var log = require("./modules/utils/logUtil.js& ...

  5. [javaEE] 数据库连接池和动态代理

    实现javax.sql.DataSource接口 实现Connection getConnection()方法 定义一个静态的成员属性LinkedList类型作为连接池,在静态代码块中初始化5条数据库 ...

  6. JAVA数据类型中的char类型

    1.JAVA中,char占2字节,16位.可在存放汉字 2.char赋值 char a='a'; //任意单个字符,加单引号. char a='中';//任意单个中文字,加单引号. char a=11 ...

  7. Gradle sync failed: Cannot set the value of read-only property 'outputFile'

    错误 Gradle sync failed: Cannot set the value of read-only property 'outputFile' 原因 gradle打包,自定义apk名称代 ...

  8. About custom Theme and Style

    For android system, of course you can custom your own style and theme, but you can't break compatibi ...

  9. Maven+Spring+MySql 登陆实例

    近来无事,复习复习Spring相关知识,从<Spring企业应用开发实战>这本书开始. 本文为学习<Spring企业应用开发实战>总结,著作权归原作者. 一.用Maven建立w ...

  10. Echarts按需引入后没有显示图例问题

    因为Echarts官网的例子都是引入整个Echarts.js.如果使用按需引入对应模块就要记得引入legend模块,才能显示出图例. 例如这样: require("echarts/lib/c ...