Apache common pool2 对象池

对象池的容器:包含一个指定数量的对象。从池中取出一个对象时,它就不存在池中,直到它被放回。在池中的对象有生命周期:创建,验证,销毁,对象池有助于更好地管理可用资源,防止JVM内部大量临时小对象,频繁触发垃圾回收,造成系统暂停。有许多的使用示例。特别是在应用服务器数据源池,线程池等都是对象池的使用,下面情况适合使用对象池:

  • 同样的对象高频率使用
  • 对象太大消耗很多内存
  • 对象初始化需要时间
  • 对象内涉及IO操作 (Streams, Sockets, DB, etc.)
  • 对象并不是线程安全时。

很多人使用 Apache Commons Pool.它有ObjectPool的接口,ObjectPoolFactory,PoolableObjectFactory和许多的实现。有addObject方法,borrowObject,invalidateObject,返回object添加,删除和返回对象。 PoolableObjectFactory定义对象池的操作行为,并提供各种回调。

但是Apache Commons Pool不是一个轻量开销的对象池,它很多方法采用了不建议使用的旧的Java的关键字synchronized。而Java 5中引入了Executor框架Java并发(多线程)。这里是最好的Executor框架。

package easypool;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public abstract class ObjectPool<T>
{
    private ConcurrentLinkedQueue<T> pool;

    private ScheduledExecutorService executorService;

    /**
     * Creates the pool.
     *
     * @param minIdle minimum number of objects residing in the pool
     */
    public ObjectPool(final int minIdle) {
        // initialize pool
        initialize(minIdle);
    }

    /**
     * Creates the pool.
     *
     * @param minIdle            minimum number of objects residing in the pool
     * @param maxIdle            maximum number of objects residing in the pool
     * @param validationInterval time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread.
     *                           When the number of objects is less than minIdle, missing instances will be created.
     *                           When the number of objects is greater than maxIdle, too many instances will be removed.
     */
    public ObjectPool(final int minIdle, final int maxIdle, final long validationInterval) {
        // initialize pool
        initialize(minIdle);

        // check pool conditions in a separate thread
        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleWithFixedDelay(new Runnable()
        {
            @Override
            public void run() {
                int size = pool.size();
                if (size < minIdle) {
                    int sizeToBeAdded = minIdle - size;
                    for (int i = 0; i < sizeToBeAdded; i++) {
                        pool.add(createObject());
                    }
                } else if (size > maxIdle) {
                    int sizeToBeRemoved = size - maxIdle;
                    for (int i = 0; i < sizeToBeRemoved; i++) {
                        pool.poll();
                    }
                }
            }
        }, validationInterval, validationInterval, TimeUnit.SECONDS);
    }

    /**
     * Gets the next free object from the pool. If the pool doesn‘t contain any objects,
     * a new object will be created and given to the caller of this method back.
     *
     * @return T borrowed object
     */
    public T borrowObject() {
        T object;
        if ((object = pool.poll()) == null) {
            object = createObject();
        }

        return object;
    }

    /**
     * Returns object back to the pool.
     *
     * @param object object to be returned
     */
    public void returnObject(T object) {
        if (object == null) {
            return;
        }

        this.pool.offer(object);
    }

    /**
     * Shutdown this pool.
     */
    public void shutdown() {
        if (executorService != null) {
            executorService.shutdown();
        }
    }

    /**
     * Creates a new object.
     *
     * @return T new object
     */
    protected abstract T createObject();

    private void initialize(final int minIdle) {
        pool = new ConcurrentLinkedQueue<T>();

        for (int i = 0; i < minIdle; i++) {
            pool.add(createObject());
        }
    }
}
package easypool;

public class ExportingProcess {

    private String location;

    private long processNo = 0;

    public ExportingProcess(String location, long processNo) {
        this.location = location;
        this.processNo = processNo;

        // doing some time expensive calls / tasks
        // ...

        // for-loop is just for simulation
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
        }

        System.out.println("Object with process no. " + processNo + " was created");
    }

    public String getLocation() {
        return location;
    }

    public long getProcessNo() {
        return processNo;
    }

    @Override
    public String toString() {
        return "ExportingProcess{" + "processNo=" + processNo + ‘}‘;
    }
}
package easypool;

public class ExportingTask implements Runnable {

    private ObjectPool<ExportingProcess> pool;

    private int threadNo;

    public ExportingTask(ObjectPool<ExportingProcess> pool, int threadNo) {
        this.pool = pool;
        this.threadNo = threadNo;
    }

    public void run() {
        // get an object from the pool
        ExportingProcess exportingProcess = pool.borrowObject();

        System.out.println("Thread " + threadNo +
                ": Object with process no. " + exportingProcess.getProcessNo() + " was borrowed");

        // do something
        // ...

        // for-loop is just for simulation
        for (int i = 0; i < 100000; i++) {
        }

        // return ExportingProcess instance back to the pool
        pool.returnObject(exportingProcess);

        System.out.println("Thread " + threadNo +
                ": Object with process no. " + exportingProcess.getProcessNo() + " was returned");
    }
}
package easypool;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class TestObjectPool
{
    private ObjectPool<ExportingProcess> pool;

    private AtomicLong processNo = new AtomicLong(0);

    @Before
    public void setUp() {
        // Create a pool of objects of type ExportingProcess. Parameters:
        // 1) Minimum number of special ExportingProcess instances residing in the pool = 4
        // 2) Maximum number of special ExportingProcess instances residing in the pool = 10
        // 3) Time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread = 5.
        //    When the number of ExportingProcess instances is less than minIdle, missing instances will be created.
        //    When the number of ExportingProcess instances is greater than maxIdle, too many instances will be removed.
        //    If the validation interval is negative, no periodical checking of minIdle / maxIdle conditions
        //    in a separate thread take place. These boundaries are ignored then.
        pool = new ObjectPool<ExportingProcess>(4, 10, 5)
        {
            protected ExportingProcess createObject() {
                // create a test object which takes some time for creation
                return new ExportingProcess("/home/temp/", processNo.incrementAndGet());
            }
        };
    }

    @After
    public void tearDown() {
        pool.shutdown();
    }

    @Test
    public void testObjectPool() {
        ExecutorService executor = Executors.newFixedThreadPool(8);

        // execute 8 tasks in separate threads
        executor.execute(new ExportingTask(pool, 1));
        executor.execute(new ExportingTask(pool, 2));
        executor.execute(new ExportingTask(pool, 3));
        executor.execute(new ExportingTask(pool, 4));
        executor.execute(new ExportingTask(pool, 5));
        executor.execute(new ExportingTask(pool, 6));
        executor.execute(new ExportingTask(pool, 7));
        executor.execute(new ExportingTask(pool, 8));

        executor.shutdown();
        try {
            executor.awaitTermination(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试》》》》》》》》》》》》》》》》》》》》》

package test;
public class StringFormat {
    public String format(String str)
    {
        return "formated:"+str;
    }
}
package test;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class StringFormatFactory
    extends BasePooledObjectFactory<StringFormat> {

    @Override
    public StringFormat create() {
        System.out.println("create object");
        return new StringFormat();
    }

    /**
     * Use the default PooledObject implementation.
     */
    @Override
    public PooledObject<StringFormat> wrap(StringFormat buffer) {
        return new DefaultPooledObject<StringFormat>(buffer);
    }

    /**
     * When an object is returned to the pool, clear the buffer.
     */
    @Override
    public void passivateObject(PooledObject<StringFormat> pooledObject) {
        System.out.println("Object been returned to pool");
    }

    // for all other methods, the no-op implementation
    // in BasePooledObjectFactory will suffice
}
package test;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class StringProcessor {

    private ObjectPool<StringFormat> pool;

    public StringProcessor(ObjectPool<StringFormat> pool) {
        this.pool = pool;
    }

    /**
     * Dumps the contents of the {@link Reader} to a String, closing the
     * {@link Reader} when done.
     */
    public void process(List<String> strList) {
        for (String str : strList) {
            Thread thread = new StringProcessThread(pool, str);
            thread.start();
        }

        //设置等待两秒,等待线程结束
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {

        GenericObjectPoolConfig conf = new GenericObjectPoolConfig();
        conf.setMaxTotal(3);
        conf.setMaxIdle(2);
        conf.setMinIdle(2);

        StringProcessor stringProcessor = new StringProcessor(
                new GenericObjectPool<StringFormat>(new StringFormatFactory(),conf));
        List<String> strList = new ArrayList<String>();
        strList.add("123");
        strList.add("456");
        strList.add("789");
        strList.add("111");
        strList.add("222");
        strList.add("333");
        stringProcessor.process(strList);
    }
}
package test;
import org.apache.commons.pool2.ObjectPool;

public class StringProcessThread extends Thread {
    private ObjectPool<StringFormat> pool;
    private String toProcessStr;

    public StringProcessThread(ObjectPool<StringFormat> pool,
            String toProcessStr) {
        this.pool = pool;
        this.toProcessStr = toProcessStr;
    }

    public void run() {
        StringFormat stringFormat = null;
        try {
            stringFormat = pool.borrowObject();
            String formattedStr = stringFormat.format(toProcessStr);
            System.out.println(formattedStr);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (stringFormat != null) {
                    pool.returnObject(stringFormat);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
时间: 2024-10-13 15:42:47

Apache common pool2 对象池的相关文章

apache的GenericObjectPool对象池使用经历!

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

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.

commons.pool2 对象池的使用

? 1 2 3 4 5 <dependency>     <groupId>org.apache.commons</groupId>     <artifactId>commons-pool2</artifactId>     <version>2.3</version> </dependency> 池对象工厂 PooledObjectFactory和池对象 DefaultPooledObject 先了解个概念

Apache Commons-pool实现对象池(包括带key对象池)

Commons-pool是一个apache开源组织下的众多项目的一个.其被广泛地整合到众多需要对象池功能的项目中. 官网:http://commons.apache.org/proper/commons-pool/ 本文是commons-pool的一个简单应用,包括不带key的池和带key的池.带key的池是把key相同的池对象放在一起池里,也就是说有多少个key就有多少个池. 不带key的池是生产完全一致的对象放在池里,但是有时候,单用对池内所有对象一视同仁的对象池,并不能解决的问题.例如,对

apache对象池的使用

Apache commons-pool本质上是"对象池",即通过一定的规则来维护对象集合的容器;commos-pool在很多场景中,用来实现"连接池"/"任务worker池"等,大家常用的dbcp数据库连接池,也是基于commons-pool实现. commons-pool实现思想非常简单,它主要的作用就是将"对象集合"池化,任何通过pool进行对象存取的操作,都会严格按照"pool配置"(比如池的大小)实

从commons pool2到池

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

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

对象池实现分析

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