commons-pool2和commons-pool对象池使用
2016-09-01 20:08
260 查看
概念
对象池(ObjectPool): 掌管对象的生命周期,获取,激活,验证,钝化,销毁等池对象(PooledObject): 被创建在池中的对象,自己可以有一些附加信息
池对象工厂(PooledObjectFactory): 池中对象各个生命周期的具体实现,怎么创建,怎么验证,怎么销毁。
对象池化主要用于减少对象在创建和销毁上面的开销,如果是小对象则不需要池化,如果是大对象可以考虑池化,对于像数据库连接、网络之类的重对象来说是很有必要池化的,开发者自己根据需求判断,如果创建某种对象成为了影响程序性能的关键因素则需要池化。
使用commons-pool2
1、maven引入:<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.2</version> </dependency>
2、创建池对象工厂,继承BasePooledObjectFactory
import org.apache.commons.pool2.BasePooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; /** * JdbcUtils工具类对象池工厂 */ public class JdbcUtilsPoolFactory extends BasePooledObjectFactory<JdbcUtils> { static GenericObjectPool<JdbcUtils> pool = null; // 取得对象池工厂实例 public synchronized static GenericObjectPool<JdbcUtils> getInstance() { if (pool == null) { GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setMaxIdle(-1); poolConfig.setMaxTotal(-1); poolConfig.setMinIdle(100); poolConfig.setLifo(false); pool = new GenericObjectPool<JdbcUtils>(new JdbcUtilsPoolFactory(), poolConfig); } return pool; } public static JdbcUtils borrowObject() throws Exception{ return (JdbcUtils) JdbcUtilsPoolFactory.getInstance().borrowObject(); } public static void returnObject(JdbcUtils jdbcUtils) throws Exception{ JdbcUtilsPoolFactory.getInstance().returnObject(jdbcUtils); } public static void close() throws Exception{ JdbcUtilsPoolFactory.getInstance().close(); } public static void clear() throws Exception{ JdbcUtilsPoolFactory.getInstance().clear(); } @Override public JdbcUtils create() throws Exception { return new JdbcUtils(); } @Override public PooledObject<JdbcUtils> wrap(JdbcUtils obj) { return new DefaultPooledObject<JdbcUtils>(obj); } }
3、使用对象池
public static void main(String[] args) throws Exception { JdbcUtils jdbcUtils = JdbcUtilsPoolFactory.borrowObject(); jdbcUtils.domestring(); JdbcUtilsPoolFactory.returnObject(jdbcUtils); }
使用commons-pool, 实现PoolableObjectFactory
1、对象BaseObjectpublic class BaseObject { //记录从池中取出次数 private int num; private boolean active; public BaseObject(){ active = true; System.out.println("new BaseObject!!!!!"); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } }
2、MyPoolableFactory对象池,实现PoolableObjectFactory
import org.apache.commons.pool.PoolableObjectFactory; public class MyPoolableFactory implements PoolableObjectFactory { //重新初始化实例返回池 @Override public void activateObject(Object arg0) throws Exception { ((BaseObject)arg0).setActive(true); } //销毁被破坏的实例 @Override public void destroyObject(Object arg0) throws Exception { arg0 = null; } //创建一个实例到对象池 @Override public Object makeObject() throws Exception { BaseObject bo = new BaseObject(); return bo; } //取消初始化实例返回到空闲对象池 @Override public void passivateObject(Object arg0) throws Exception { ((BaseObject)arg0).setActive(false); } //验证该实例是否安全 @Override public boolean validateObject(Object arg0) { if(((BaseObject)arg0).isActive()) return true; else return false; } }
3、测试PoolableObjectFactory
import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool; /* * 这里的池声明用ObjectPool或者GenericObjectPool的区别在于: * (1)ObjectPool : GenericObjectPool这种对象池的特色是: 可以设定最多能从池中借出多少个对象。 可以设定池中最多能保存多少个对象。 可以设定在池中已无对象可借的情况下,调用它的borrowObject方法时的行为,是等待、创建新的实例还是抛出异常。 可以分别设定对象借出和还回时,是否进行有效性检查。 可以设定是否使用一个单独的线程,对池内对象进行后台清理。 …… StackObjectPool:使用LIFO行为实现的ObjectPool。 SoftReferenceObjectPool: 使用LIFO行为实现的ObjectPool。此外,在这个对象池实现中,每个对象都会被包装到一个SoftReference中。 SoftReference允许垃圾回收机制在需要释放内存时回收对象池中的对象。 源码GenericObjectPool.java类内部的setConfig方法 1. 参数maxActive指明能从池中借出的对象的最大数目。如果这个值不是正数,表示没有限制。 2. 参数whenExhaustedA ction指定在池中借出对象的数目已达极限的情况下,调用它的borrowObject方法时的行为。可以选用的值有: GenericObjectPool.WHEN_EXHAUSTED_BLOCK,表示等待; GenericObjectPool.WHEN_EXHAUSTED_GROW,表示创建新的实例(不过这就使maxActive参数失去了意义); GenericObjectPool.WHEN_EXHAUSTED_FAIL,表示抛出一个java.util.NoSuchElementException异常。 3. 参数maxWait指明若在对象池空时调用borrowObject方法的行为被设定成等待,最多等待多少毫秒。如果等待时间超过了这个数值,则会抛出一个java.util.NoSuchElementException异常。如果这个值不是正数,表示无限期等待。 4. 参数testOnBorrow设定在借出对象时是否进行有效性检查。 5. 参数testOnBorrow设定在还回对象时是否进行有效性检查。 6. 参数timeBetweenEvictionRunsMillis,设定间隔每过多少毫秒进行一次后台对象清理的行动。如果这个值不是正数,则实际上不会进行后台对象清理。 7. 参数minEvictableIdleTimeMillis,设定在进行后台对象清理时,视休眠时间超过了多少毫秒的对象为过期。过期的对象将被回收。如果这个值不是正数,那么对休眠时间没有特别的约束。 8. 参数testWhileIdle,则设定在进行后台对象清理时,是否还对没有过期的池内对象进行有效性检查。不能通过有效性检查的对象也将被回收。 9. 参数lifo,池对象的放入和取出默认是后进先出的原则,默认是true,代表后进先出,设置为false代表先进先出。 */ public class PoolTest { public static void main(String[] args) { BaseObject bo = null; PoolableObjectFactory factory = new MyPoolableFactory(); GenericObjectPool pool = new GenericObjectPool(factory); //这里两种池都可以,区别下文会提到 //ObjectPool pool = new StackObjectPool(factory); try { for(int i = 0; i < 5; i++) { System.out.println("\n==========="+i+"==========="); System.out.println("池中处于闲置状态的实例pool.getNumIdle():"+pool.getNumIdle()); //从池里取一个对象,新创建makeObject或将以前闲置的对象取出来 bo = (BaseObject)pool.borrowObject(); System.out.println("bo:"+bo); System.out.println("池中所有在用实例数量pool.getNumActive():"+pool.getNumActive()); if((i%2) == 0) { //用完之后归还对象 pool.returnObject(bo); System.out.println("归还对象!!!!"); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if(bo != null) { pool.returnObject(bo); } //关闭池 pool.close(); } catch (Exception e) { e.printStackTrace(); } } } }
使用commons-pool, 实现KeyedPoolableObjectFactory
1、创建对象BaseObject, 代码同上2、创建MyKeyPoolableFactory, 实现KeyedPoolableObjectFactory
import org.apache.commons.pool.KeyedPoolableObjectFactory; public class MyKeyPoolableFactory implements KeyedPoolableObjectFactory { //重新初始化实例返回池 @Override public void activateObject(Object arg0, Object arg1) throws Exception { ((BaseObject)arg1).setActive(true); } //销毁被破坏的实例 @Override public void destroyObject(Object arg0, Object arg1) throws Exception { arg1 = null; } //创建一个实例到对象池 @Override public Object makeObject(Object arg0) throws Exception { //这里从数据库里查询出使用次数最少的配置 BaseObject bo = new BaseObject(); bo.setNum(0); return bo; } //取消初始化实例返回到空闲对象池 @Override public void passivateObject(Object arg0, Object arg1) throws Exception { ((BaseObject)arg1).setActive(false); } //验证该实例是否安全 true:正在使用 @Override public boolean validateObject(Object arg0, Object arg1) { //这里可以判断实例状态是否可用 if(((BaseObject)arg1).isActive()) return true; else return false; } }
3、测试MyKeyPoolableFactory
import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.apache.commons.pool.impl.GenericKeyedObjectPool; public class KeyPoolTest { public static void main(String[] args) { BaseObject bo = null; BaseObject bo1 = null; BaseObject bo2 = null; KeyedPoolableObjectFactory keyFactory = new MyKeyPoolableFactory(); GenericKeyedObjectPool keyPool = new GenericKeyedObjectPool(keyFactory); //keyPool.setLifo(false); try { //这里添加池对象,只需要传入key就会默认调用makeObject()方法创建一个对象 keyPool.addObject("一级"); keyPool.addObject("二级"); //这里注释掉,不初始创建这个键的池对象 //keyPool.addObject("三级"); System.out.println("池中处于闲置状态的实例pool.getNumIdle():"+keyPool.getNumIdle()); for (int i = 0; i < 5; i++) { //从池里取对象 bo = (BaseObject) keyPool.borrowObject("一级"); bo.setNum(bo.getNum()+1); System.out.println("一级"+i+"-------"+bo+"-------"+bo.getNum()); bo1 = (BaseObject) keyPool.borrowObject("二级"); bo1.setNum(bo1.getNum()+1); System.out.println("二级"+i+"-------"+bo1+"-------"+bo1.getNum()); //上边注释掉的那行代码,这里取对象的时候如果没有闲置对象,也会默认去创建一个key="三级"的池对象 bo2 = (BaseObject) keyPool.borrowObject("三级"); bo2.setNum(bo2.getNum()+1); System.out.println("三级"+i+"-------"+bo2+"-------"+bo2.getNum()); if(i<3) { //用完之后归还对象 keyPool.returnObject("一级", bo); keyPool.returnObject("二级", bo1); keyPool.returnObject("三级", bo2); System.out.println("归还对象!!!"); } } //当前池里的实例数量 System.out.println("池中所有在用实例pool.getNumActive():"+keyPool.getNumActive()); //当前池里的处于闲置状态的实例 System.out.println("池中处于闲置状态的实例pool.getNumIdle():"+keyPool.getNumIdle()); } catch (Exception e) { e.printStackTrace(); } //这里就不写finally了,偷懒了,这里应该关闭池的 } }
相关文章推荐
- commons-pool2对象池使用
- commons-pool对象池实现原理及使用(一)
- commons-fileupload-1.0上传组件使用实例.
- commons-logging与log4j的结合使用说明与示例
- 使用struts相关组件上传附件(org.apache.commons.fileupload.*)上传附件--详解
- Struts中使用commons-fileupload实现上传例子
- 巧妙使用spring对commons fileUpload的包装
- 使用commons-logging记录日志信息
- 使用commons-logging的笔记
- 使用commons-dbutils进行JDBC项目开发
- 文件上传和下载的commons-fileupload-1.2的使用
- jakarta commons logging 的使用方法
- 使用commons-email发邮件
- jakartacommonslogging的使用方法
- commons-fileupload-1.0上传组件使用实例.
- 关于Jakarta-Commons下载使用的问题
- log4j和commons.logging日志记录的使用方法
- org.apache.commons.fileupload的使用
- 使用Commons-net包实现ftp服务器的访问
- org.apache.commons.digester.Digester使用 [待续]