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==============

时间: 2024-11-05 18:27:18

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

从commons pool2到池

转载请注明:http://blog.csdn.net/HEL_WOR/article/details/51224388 池该如何理解?我们经常提到的数据库连接池,线程池,对象池. 池这个概念,在计算机里,应该如何用代码来描述? 在网页上可以找到很多关于数据库连接池的描述,实现DataSource接口,用一个链表或者只要能保存数据的容器将事先创建好的连接保存起来,一个连接池就成型了,在需要使用的时候去容器里取出一个连接,使用完毕后归还这个连接,如果想要重写close方法让连接归还到容器中而不是被关

Apache Commons Pool2连接池代码

2013年,Apache Commons Pool 2.0 发布,这是一个完全重写的对象池的实现.实现的代码和原来差异很大,原来的一些例子就不能用了.按照上面的例子,用pool2的类和方法重写下. ApacheCommons Pool 2.0 代码如下: package test.ffm83.commons.pool; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.lang.

Apache common pool2 对象池

对象池的容器:包含一个指定数量的对象.从池中取出一个对象时,它就不存在池中,直到它被放回.在池中的对象有生命周期:创建,验证,销毁,对象池有助于更好地管理可用资源,防止JVM内部大量临时小对象,频繁触发垃圾回收,造成系统暂停.有许多的使用示例.特别是在应用服务器数据源池,线程池等都是对象池的使用,下面情况适合使用对象池: 同样的对象高频率使用 对象太大消耗很多内存 对象初始化需要时间 对象内涉及IO操作 (Streams, Sockets, DB, etc.) 对象并不是线程安全时. 很多人使用

连接池Commons Pool2的使用

客户端这边,如果每次都临时建立一个新的连接,那么连接的开销非常大. 业内常用的连接池组件是 Commons Pool2---版本 2.4.2 ==================具体代码如下:[http://commons.apache.org/proper/commons-pool/examples.html] package service.pool; import org.apache.commons.pool2.BasePooledObjectFactory; import org.ap

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

Apache Commons Pool实现了对象池的功能.定义了对象的生成.销毁.激活.钝化等操作及其状态转换,并提供几个默认的对象池实现.在讲述其实现原理前,先提一下其中有几个重要的对象: PooledObject(池对象). PooledObjectFactory(池对象工厂). Object Pool(对象池). 下面分别详细讲解它们的实现. PooledObject(池对象) 用于封装对象(如:线程.数据库连接.TCP连接),将其包裹成可被池管理的对象.提供了两个默认的池对象实现: De

大数据技术之_27_电商平台数据分析项目_02_预备知识 + Scala + Spark Core + Spark SQL + Spark Streaming + Java 对象池

第0章 预备知识0.1 Scala0.1.1 Scala 操作符0.1.2 拉链操作0.2 Spark Core0.2.1 Spark RDD 持久化0.2.2 Spark 共享变量0.3 Spark SQL0.3.1 RDD.DataFrame 与 DataSet0.3.2 DataSet 与 RDD 互操作0.3.3 RDD.DataFrame 与 DataSet 之间的转换0.3.4 用户自定义聚合函数(UDAF)0.3.5 开窗函数0.4 Spark Streaming0.4.1 Dst

对象池实现分析

对象池实现分析 什么是对象池技术?对象池应用在哪些地方? 对象池其实就是缓存一些对象从而避免大量创建同一个类型的对象,类似线程池的概念.对象池缓存了一些已经创建好的对象,避免需要时才创建对象,同时限制了实例的个数.池化技术最终要的就是重复的使用池内已经创建的对象.从上面的内容就可以看出对象池适用于以下几个场景: 创建对象的开销大 会创建大量的实例 限制一些资源的使用 如果创建一个对象的开销特别大,那么提前创建一些可以使用的并且缓存起来(池化技术就是重复使用对象,提前创建并缓存起来重复使用就是池化

Netty轻量级对象池实现分析

什么是对象池技术?对象池应用在哪些地方? 对象池其实就是缓存一些对象从而避免大量创建同一个类型的对象,类似线程池的概念.对象池缓存了一些已经创建好的对象,避免需要时才创建对象,同时限制了实例的个数.池化技术最终要的就是重复的使用池内已经创建的对象.从上面的内容就可以看出对象池适用于以下几个场景: 创建对象的开销大 会创建大量的实例 限制一些资源的使用 如果创建一个对象的开销特别大,那么提前创建一些可以使用的并且缓存起来(池化技术就是重复使用对象,提前创建并缓存起来重复使用就是池化)可以降低创建对

apache的GenericObjectPool对象池使用经历!

今天,对照晚上的kafka+Spark streaming+Redis实时数据分析系统实战(https://www.iteblog.com/archives/1378 主要目的是整合kafka和Spark,Redis. Redis一直没用过,所以比较犯难,果然,在前面都没什么问题,后面的redis部分,遇到了一个问题: 没有发现GenericObjectPoolConfig这个类. 百度了好久,一直找不到解决的办法,后来,才明白,这应该是个maven的库包,所以,在 http://maven.o