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. 带有Apache Spark的Lambda架构

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 目标 市场上的许多玩家已经建立了成功的MapReduce工作流程来每天处理以TB计的历史数据.但是谁愿意等待24小时才能获得最新的分析结果? ...

  2. 【curl】Linux下命令行curl详解

    在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具.它支持文件的上传和下载,是综合传输工具,但按传统,习惯称url为下载工具. 语法:# c ...

  3. struts2随笔

    1.struts.properties配置常量等同于struts.xml中配置(置于类加载路径下面)struts.multipart.maxSize文件上传最大大小struts.action.exte ...

  4. Nginx配置整理

    不论是本地开发,还是远程到 Server 开发,还是给提供 demo 给人看效果,我们时常需要对 Nginx 做配置,Nginx 的配置项相当多,如果考虑性能配置起来会比较麻烦.不过,我们往往只是需要 ...

  5. Java 基础(6)——关键字 & 标识符 & 转义字符

    依然是基础的一天,看一看就好~ 关键字 之前就有说过关键字哦~ 注:关键字就是程序发明者规定的有特殊含义的单词. from Java基础(2) Java 中除了关键字以外还有暂时没有成为关键字的保留字 ...

  6. 三个缓存数据库Redis、Memcache、MongoDB

    >>Memcached Memcached的优点:Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key.value的字节大小以及服务器硬件性能,日常环境 ...

  7. golang 应用的部署相关技术

    nohup命令 在 linux 下面部署,我们可以利用 nohup 命令,把应用部署在后端,如下所示: nohup ./yourapp & 这样你的应用就跑在了 Linux 系统的守护进程 n ...

  8. 2048小游戏4X4C语言

    */ #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<time.h> v ...

  9. 编写简单的maven插件

    编写一个简单的输出maven的hello world的插件 1.在eclipse中新建一个maven project项目 然后取名HelloPlugin,建立后,pom文件为(注意packaging为 ...

  10. mybatis向数据库插入数据 (传入的是一个实体类)

    /** * 插入用户信息 user为实体类 * @param user */ public int insert( User user); //实体类不用@param标注 //mybatis的xml文 ...