概念

  对象池(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();}@Overridepublic JdbcUtils create() throws Exception {return new JdbcUtils();}@Overridepublic 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、对象BaseObject

public 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对象池使用相关推荐

  1. Golang sync.pool对象池

    概览 Goalng中通过sync.pool提供了对象池的实现来达到对象复用的目的.在netty中,也通过Recycle类实现了类似的对象池实现.在netty的对象池Recycle中,当A线程需要将B线 ...

  2. 对象池——Smiple Pool For Unity

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/54096845 作者:car ...

  3. commons-pool2自定义对象池-快速开始

    文章目录 一.什么是commons-pool2 1. springboot使用commons-pool2实现对象池 二.常用API 1. GenericObjectPool 2. PooledObje ...

  4. 深入研究池化技术——对象池

    池化技术 池化技术是性能调优的重要措施,池化的思想是把对象放到池子里,当要使用的时候,从池子里面拿对象,用完后再放回池子里,这样可以降低资源分配以及释放的开销,从而提升性能,在实际项目中,其实我们每天 ...

  5. Golang对象池实现

    一.sync.Pool定义 我们通常用golang来构建高并发场景下的应用,但是由于golang内建的GC机制会影响应用的性能,为了减少GC,golang提供了对象重用的机制,也就是sync.Pool ...

  6. Unity对象池简单应用

    1.简单介绍 在Unity开发过程中,对象池是一种很好的能用于减少内存开销的方式.在许多场景中,比如角色射击出去的子弹,以及在游戏运行过程中频繁生成的敌人-如果在运行时实时在场景中Instance和D ...

  7. commons.pool2 对象池的使用

    commons.pool2 对象池的使用 ? 1 2 3 4 5 <dependency>     <groupId>org.apache.commons</groupI ...

  8. common pool2 mysql_连接池Commons Pool2的使用

    客户端这边,如果每次都临时建立一个新的连接,那么连接的开销非常大. 业内常用的连接池组件是 Commons Pool2---版本 2.4.2 packageservice.pool; importor ...

  9. 面试官问:对象池技术了解吗?apache common pool2呢?

    欢迎关注方志朋的博客,回复"666"获面试宝典 对象池顾名思义就是存放对象的池,与我们常听到的线程池.数据库连接池.http连接池等一样,都是典型的池化设计思想. 对象池的优点就是 ...

  10. golang的临时对象池sync.Pool

    今天在写码之时,发现了同事用到了sync.pool.因不知其因,遂Google之.虽然大概知道其原因和用法.还不能融汇贯通.故写此记,方便日后查阅.直至明了. 正文 在高并发或者大量的数据请求的场景中 ...

最新文章

  1. 流程图函数’怎么画_原来函数可以这么美!
  2. 关于验证码整理的新版本
  3. 使用Tensorflow构建和训练自己的CNN来做简单的验证码识别
  4. SpringMVC框架的详细操作步骤和注解的用法
  5. Linux和optee双系统中1020-1023号的中断号的使用
  6. 直接用自己服务器做图床可以吗_我花 9 块钱搭了一个“私人图床”
  7. GoogleNet网络详解与keras实现
  8. (48)FPGA面试题sram,falsh memory,及dram的区别
  9. Java CAS无锁技术深度解析
  10. 【 2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛】1002.array【主席树】
  11. officescan使用apache跳轉設置
  12. 合作、高效 -- 下一代汽车电子软件开发与测试论坛
  13. 软件开发流程:需求评审流程
  14. 富士施乐Fuji Xerox DocuCentre-II 6000 驱动
  15. SpringCloud Alibaba(四) Nacos服务端本地启动和源码浅析(AP架构),Distro协议介绍,CAP原则介绍
  16. YOLOX安装部署使用训练教程以及报错
  17. oracle出现ora 12514,ora-12514报错解决方法
  18. 美国公布自动驾驶新政AV4.0;微软Access数据库出现漏洞,或致8.5万家企业面临风险;苹果谈论隐私问题……...
  19. 目标检测单阶段、双阶段检测框部分学习总结
  20. 街头霸王5显示正在登陆服务器无法进入游戏,街头霸王5打不开怎么办 无法进入游戏解决方法...

热门文章

  1. Kafka中ACKS LSO LEO LW HW AR ISR OSR解析
  2. mysqld --initialize 没有反应_铁道物语:陆王--出场惊艳,玩法磨人
  3. P2614 计算器弹琴
  4. Marble原理之线程池
  5. 图像风格迁移做了一件文化衫-【布尔艺数】
  6. 实用微带线的相关计算
  7. 百度松果人才OJ赛第一场
  8. 【MySQL体系结构】MySQL8.0物理文件结构
  9. Editor markdown编辑器
  10. 苹果笔记本好吗_在大学里,笔记本真的比台式电脑好吗?