java对象池commons-pool-1.6详解(二)
来源:互联网 发布:vb net从入门到精通 编辑:程序博客网 时间:2024/05/23 14:42
一、重点接口介绍:
在Apache-commons-pool-1.6中,对不带key的对象池定义了三个顶级接口:ObjectPool、ObjectPoolFactory、PoolableObjectFactory;其中ObjectPool和ObjectPoolFactory在功能上是一样的(都有三个不同的实现类),不同点仅在于使用上不同(后者通过工厂的方式使用),具体实例见后面。PoolableObjectFactory是池化对象接口,被池化的对象需要实现该接口。
1)对象池接口:
ObjectPool接口用于管理要被池化对象的借出(borrowObject)、归还(returnObject)、失效移除(invalidateObject)、预加载(addObject)以及对象池的清空(clear、close)等,它通过PoolableObjectFactory来完成相应对象的各种操作。ObjectPoolFactory接口是对ObjectPool接口的工厂化封装,用于生产ObjectPool接口。
2)池化对象接口:
PoolableObjectFactory用于管理被池化对象(被池化的对象需要实现该接口),主要功能包括对象的产生(makeObject),激活(activateObject),挂起(passivateObject),检验(validateObject)和销毁(destroyObject)
二、对象池使用流程:
1)使用者通过对象池(ObjectPool/ObjectPoolFactory)接口实现类中的borrowObject方法来从对象池中获取对象,并将active标记+1;
- 如果池中有idle的对象(idle>0),直接返回该对象,并将idle-1;
- 如果池中没有idle的对象,调用池化对象接口实现类中的makeObject方法创建对象;如果目前对象池的active数达到maxactive,那么阻塞等待;
- 如果配置了testonborrow=ture,那么在获取对象之前还会调用池化对象接口PoolableObjectFactory的实现类中validateObject方法来检验对象的有效性,如果非法则直接调用PoolableObjectFactory接口的实现类中destroyObject方法销毁;
2)使用完对象必须要归还给对象池,通过对象池(ObjectPool/ObjectPoolFactory)接口的实现类中的returnObject方法将对象归还到对象池中,并将active标记-1;
- 如果配置了testonreturn=ture,那么在归还对象前还会调用池化对象接口PoolableObjectFactory的实现类中validateObject方法来检验对象的有效性,如果非法则直接调用PoolableObjectFactory接口的实现类中destroyObject方法销毁;
- 如果idle数大于maxidle,则销毁对象,否则唤醒上面阻塞的进程或者放到idle区(idle+1);
- 如果配置了removeAbandonedTimeout,则超过该事件的池化对象直接进入放逐区;
注:对象池只有在borrowObject的时候才回去真正创建对象(调用makeObject或者从池中的idle队列中获取),如果要预申请对象,需要调用吃对象接口ObjectPool的addObject方法。
三、对象池实现类:
ObjectPool接口下面有三个实现类:GenericObjectPool、StackObjectPool、SoftReferenceObjectPool。
1、genericObjectpool:(重点)
GenericObjectPool采用LIFO/FIF,池的默认行为是一个LIFO,这就意味着,当池中有空闲可用的对象时,调用borrowObject方法会返回最近(“后进”)的实例。如果LIFO策略在池中是false的,实例的返回按相反的顺序,-先进 - 先出。它利用一个org.apache.commons.collections.CursorableLinkedList对象来保存对象池里的对象。
1)这种对象池的特色是:
- 可以设定最多能从池中借出多少个对象。
- 可以设定池中最多能保存多少个对象。
- 可以设定在池中已无对象可借的情况下,调用它的borrowObject方法时的行为,是等待、创建新的实例还是抛出异常。
- 可以分别设定对象借出和还回时,是否进行有效性检查。
- 可以设定是否使用一个单独的线程,对池内对象进行后台清理。
2)构造函数:
GenericObjectPool一共7个构造函数,最简单的是GenericObjectPool(PoolableObjectFactory factory),仅仅指明要用的PoolableObjectFactory实例,其它参数则采用默认值;此外可以通过GenericObjectPool(PoolableObjectFactory factory, GenericObjectPool.Config config) 构造函数来构造复杂的配置,其中GenericObjectPool.Config可以设置:
- int maxActive
- int maxIdle
- long maxWait
- long minEvictableIdleTimeMillis
- int numTestsPerEvictionRun
- boolean testOnBorrow
- boolean testOnReturn
- boolean testWhileIdle
- long timeBetweenEvictionRunsMillis
- byte whenExhaustedAction
2、StackObjectPool:
StackObjectPool采用LIFO,利用一个java.util.Stack对象来保存对象池里的对象。
1)这种对象池的特色是:
- 可以为对象池指定一个初始的参考大小(当空间不够时会自动增长)。
- 在对象池已空的时候,调用它的borrowObject方法,会自动返回新创建的实例。
- 可以为对象池指定一个可保存的对象数目的上限。达到这个上限之后,再向池里送回的对象会被自动送去回收。
2)构造函数:
StackObjectPool一共6个构造函数,最简单的一个是StackObjectPool(),一切采用默认的设置,也不指明要用的PoolableObjectFactory实例;最复杂的一个则是StackObjectPool(PoolableObjectFactory factory, int max, int init),其中参数factory指明要与之配合使用的PoolableObjectFactory实例、参数max设定可保存对象数目的上限、参数init则指明初始的参考大小。
3、SoftReferenceObjectPool:
SoftReferenceObjectPool采用LIFO,这种池额外功能是包装了每一个引用对象,允许GC根据内存需求清除这些对象。利用一个java.util.ArrayList对象来保存对象池里的对象。不过它并不在对象池里直接保存对象本身,而是保存它们的“软引用”(Soft Reference)。
1)这种对象池的特色是:
- 可以保存任意多个对象,不会有容量已满的情况发生。
- 在对象池已空的时候,调用它的borrowObject方法,会自动返回新创建的实例。
- 可以在初始化同时,在池内预先创建一定量的对象。
- 当内存不足的时候,池中的对象可以被Java虚拟机回收。
2)构造方法:
SoftReferenceObjectPool有3个构造方法,最简单的是SoftReferenceObjectPool(),不预先在池内创建对象,也不指明要用的PoolableObjectFactory实例;最复杂的一个则是SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize)。其中:参数factory指明要与之配合使用的PoolableObjectFactory实例、参数initSize则指明初始化时在池中创建多少个对象
四、实例:
1)定义一个被池化的对象:
package cn.eud.nuc.pool.bean;public class MyBean {private Long id;private String name;private String other;public void abc(int inxtInt) throws InterruptedException {Thread.sleep(1000);System.out.println(this.toString());}public MyBean(Long id, String name, String other) {super();this.id = id;this.name = name;this.other = other;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getOther() {return other;}public void setOther(String other) {this.other = other;}@Overridepublic String toString() {return "MyBean [id=" + id + ", name=" + name + ", other=" + other + "]";}}2)实现池化接口:
package cn.eud.nuc.pool.bean;import java.util.concurrent.ThreadLocalRandom;import org.apache.commons.pool.BasePoolableObjectFactory;public class MyBeanPool extends BasePoolableObjectFactory<MyBean>{private ThreadLocalRandom random = ThreadLocalRandom.current();@Overridepublic MyBean makeObject() throws Exception {System.out.println("make...");long id = random.nextLong(10000000);return new MyBean(id,System.currentTimeMillis()+"_test","");}@Overridepublic void destroyObject(MyBean client) throws Exception {System.out.println("======================================================destroy...");}@Overridepublic boolean validateObject(MyBean client) {return true;}}3)测试类1:(使用GenericObjectPool接口)
package cn.eud.nuc.pool;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadLocalRandom;import org.apache.commons.pool.impl.GenericObjectPool;import cn.eud.nuc.pool.bean.MyBean;import cn.eud.nuc.pool.bean.MyBeanPool;public class Test {public static void main(String...strings) throws Exception {MyBeanPool myBeanPool = new MyBeanPool();GenericObjectPool.Config poolConfig = new GenericObjectPool.Config();poolConfig.maxActive = 100;poolConfig.maxIdle = 1;//poolConfig.minIdle = 0;poolConfig.minEvictableIdleTimeMillis = 1000000000;poolConfig.timeBetweenEvictionRunsMillis = 10 * 2L;poolConfig.testOnBorrow=false;poolConfig.testOnReturn=true;poolConfig.testWhileIdle=true;poolConfig.lifo = false;//poolConfig.maxWait = 100000000;GenericObjectPool<MyBean> genericObjectPool = new GenericObjectPool<MyBean>(myBeanPool, poolConfig);genericObjectPool.addObject();genericObjectPool.addObject();genericObjectPool.addObject();genericObjectPool.addObject();ExecutorService pool = Executors.newFixedThreadPool(200);for (int i=0;i<5000;i++) {pool.submit(new MyThread(genericObjectPool));}}}class MyThread implements Runnable {private ThreadLocalRandom random = ThreadLocalRandom.current();private GenericObjectPool<MyBean> genericObjectPool;public MyThread(GenericObjectPool<MyBean> genericObjectPool) {super();this.genericObjectPool = genericObjectPool;}@Overridepublic void run() {int nextInt = random.nextInt(100);MyBean borrowObject = null;boolean flag = true;try {borrowObject = genericObjectPool.borrowObject();borrowObject.abc(nextInt);} catch (Exception e) {flag = false;e.printStackTrace();} finally {try {if (flag) {genericObjectPool.returnObject(borrowObject);} else {genericObjectPool.invalidateObject(borrowObject);}} catch (Exception e) {e.printStackTrace();}}}}
package cn.eud.nuc.pool;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadLocalRandom;import org.apache.commons.pool.ObjectPool;import org.apache.commons.pool.impl.GenericObjectPool;import org.apache.commons.pool.impl.GenericObjectPoolFactory;import cn.eud.nuc.pool.bean.MyBean;import cn.eud.nuc.pool.bean.MyBeanPool;public class Test2 {public static void main(String...strings) throws InterruptedException {MyBeanPool myBeanPool = new MyBeanPool();GenericObjectPool.Config poolConfig = new GenericObjectPool.Config();poolConfig.maxActive = 100;poolConfig.maxIdle = 1;//poolConfig.minIdle = 0;poolConfig.minEvictableIdleTimeMillis = 1000000000;poolConfig.timeBetweenEvictionRunsMillis = 10 * 2L;poolConfig.testOnBorrow=false;poolConfig.testOnReturn=true;poolConfig.testWhileIdle=true;poolConfig.lifo = false;//poolConfig.maxWait = 100000000;GenericObjectPoolFactory<MyBean> genericObjectPoolFactory = new GenericObjectPoolFactory<>(myBeanPool, poolConfig);ObjectPool<MyBean> createPool = genericObjectPoolFactory.createPool();ExecutorService pool = Executors.newFixedThreadPool(200);for (int i=0;i<5000;i++) {pool.submit(new MyThread1(createPool));}}}class MyThread1 implements Runnable {private ThreadLocalRandom random = ThreadLocalRandom.current();private ObjectPool<MyBean> genericObjectPool;public MyThread1(ObjectPool<MyBean> genericObjectPool) {super();this.genericObjectPool = genericObjectPool;}@Overridepublic void run() {int nextInt = random.nextInt(100);MyBean borrowObject = null;boolean flag = true;try {borrowObject = genericObjectPool.borrowObject();borrowObject.abc(nextInt);} catch (Exception e) {flag = false;e.printStackTrace();} finally {try {if (flag) {genericObjectPool.returnObject(borrowObject);} else {genericObjectPool.invalidateObject(borrowObject);}} catch (Exception e) {e.printStackTrace();}}}}
参考:
https://www.cnblogs.com/shipengzhi/archive/2011/06/02/2068565.html
- java对象池commons-pool-1.6详解(二)
- java对象池commons-pool-1.6详解(一)
- java对象池commons-pool-1.6详解(三)
- Java笔记之对象池1(commons-pool)
- Java笔记之对象池2(commons-pool)
- 对象池commons-pool
- java 对象池(GenericObjectPool)优化——commons-pool-1.6.jar
- commons-pool对象池(1)---总结
- 使用Jakarta Commons Pool处理对象池化(二)(zt)
- commons-pool对象池实现原理及使用(二)
- commons-pool对象池技术
- 对象池commons-pool框架的研究以及源代码分析(二)
- Java模块 -- Apache Commons Pool 对象池_简介
- commons-pool对象池(2)---实现一个线程池
- 使用Jakarta Commons Pool处理对象池化(zz)
- Commons Pool处理对象池化分析(1)
- Jakarta Commons Pool 对象池 使用,测试
- Apache commons-pool对象池原理分析
- File常用API总结
- 计算有效工作日(跳过节假日)
- 立方体的体积
- 系统目录
- java-IO常用集合API
- java对象池commons-pool-1.6详解(二)
- 软件测试知识点
- 二叉树从根节点到叶子节点路径 C语言
- 巧用a标签解析url
- 3D引擎数据结构与glTF(2): Scene Graph
- Django使用表单操作数据库
- github 开启两步认证后 不能 git clone 和 git push
- 【XSY2666】排列问题 DP 容斥原理 分治FFT
- Unity面向组件开发