前面两篇文章说了怎么样简单的使用commons-pool库,这里需要考虑一个问题就是在很多时候我们在池里的对象都是比较重型的并且大多数比较稀缺的 资源,比如说数据库连接,这样如果一直把一些连接放在池里不归还,就会很占资源,并且是这些资源利用率降低,那么怎样才能更好的管理池子中的资源 呢,commons-pool里提供了一个GenericObjectPool类,它的出现使上面的问题就迎刃而解了。同样对于 GenericObjectPool类,也就有一个对应的GenericKeyedObjectPool类。

下面还是例子说话

一个Connection类,可以想象成一个远程连接比如数据库连接等。其中包括创建连接,关闭连接,和一个print方法。

  1. package com.googlecode.garbagecan.commons.pool.sample3;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. public class MyConnection {
  5. private static Logger logger = LoggerFactory.getLogger(MyConnection.class);
  6. private String name;
  7. private boolean connected;
  8. public MyConnection(String name) {
  9. this.name = name;
  10. }
  11. public void connect() {
  12. this.connected = true;
  13. logger.info(name + ": " + connected);
  14. }
  15. public void close() {
  16. this.connected = false;
  17. logger.info(name + ": " + connected);
  18. }
  19. public boolean isConnected() {
  20. return this.connected;
  21. }
  22. public String getName() {
  23. return this.name;
  24. }
  25. public void print() {
  26. logger.info(this.name);
  27. }
  28. }

一个PoolableObjectFactory接口的实现类,提供makeObject, activateObject, passivateObject, validateObject, destroyObject方法。

  1. package com.googlecode.garbagecan.commons.pool.sample3;
  2. import org.apache.commons.pool.PoolableObjectFactory;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. public class MyConnectionPoolableObjectFactory implements PoolableObjectFactory {
  6. private static Logger logger = LoggerFactory.getLogger(MyConnectionPoolableObjectFactory.class);
  7. private static int count = 0;
  8. public Object makeObject() throws Exception {
  9. MyConnection myConn = new MyConnection(generateName());
  10. logger.info(myConn.getName());
  11. myConn.connect();
  12. return myConn;
  13. }
  14. public void activateObject(Object obj) throws Exception {
  15. MyConnection myConn = (MyConnection)obj;
  16. logger.info(myConn.getName());
  17. }
  18. public void passivateObject(Object obj) throws Exception {
  19. MyConnection myConn = (MyConnection)obj;
  20. logger.info(myConn.getName());
  21. }
  22. public boolean validateObject(Object obj) {
  23. MyConnection myConn = (MyConnection)obj;
  24. logger.info(myConn.getName());
  25. return myConn.isConnected();
  26. }
  27. public void destroyObject(Object obj) throws Exception {
  28. MyConnection myConn = (MyConnection)obj;
  29. logger.info(myConn.getName());
  30. myConn.close();
  31. }
  32. private synchronized String generateName() {
  33. return "conn_" + (++count);
  34. }
  35. }

一个测试类

  1. package com.googlecode.garbagecan.commons.pool.sample3;
  2. import org.apache.commons.pool.ObjectPool;
  3. import org.apache.commons.pool.PoolableObjectFactory;
  4. import org.apache.commons.pool.impl.GenericObjectPool;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. public class Test {
  8. private static Logger logger = LoggerFactory.getLogger(Test.class);
  9. public static void main(String[] args) {
  10. //test1();
  11. //test2();
  12. //test3();
  13. }
  14. private static void test1() {
  15. PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();
  16. GenericObjectPool.Config config = new GenericObjectPool.Config();
  17. config.lifo = false;
  18. config.maxActive = 5;
  19. config.maxIdle = 5;
  20. config.minIdle = 1;
  21. config.maxWait = 5 * 1000;
  22. ObjectPool pool = new GenericObjectPool(factory, config);
  23. for (int i = 0; i < 10; i++) {
  24. Thread thread = new Thread(new MyTask(pool));
  25. thread.start();
  26. }
  27. //closePool(pool);
  28. }
  29. private static void test2() {
  30. PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();
  31. GenericObjectPool.Config config = new GenericObjectPool.Config();
  32. config.lifo = false;
  33. config.maxActive = 5;
  34. config.maxIdle = 5;
  35. config.minIdle = 1;
  36. config.maxWait = 20 * 1000;
  37. ObjectPool pool = new GenericObjectPool(factory, config);
  38. for (int i = 0; i < 10; i++) {
  39. Thread thread = new Thread(new MyTask(pool));
  40. thread.start();
  41. }
  42. //closePool(pool);
  43. }
  44. private static void test3() {
  45. PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();
  46. GenericObjectPool.Config config = new GenericObjectPool.Config();
  47. config.lifo = false;
  48. config.maxActive = 5;
  49. config.maxIdle = 0;
  50. config.minIdle = 0;
  51. config.maxWait = -1;
  52. ObjectPool pool = new GenericObjectPool(factory, config);
  53. Thread thread = new Thread(new MyTask(pool));
  54. thread.start();
  55. try {
  56. Thread.sleep(60L * 1000L);
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. }
  60. //closePool(pool);
  61. }
  62. private static void closePool(ObjectPool pool) {
  63. try {
  64. pool.close();
  65. } catch (Exception e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. private static class MyTask implements Runnable {
  70. private ObjectPool pool;
  71. public MyTask(ObjectPool pool) {
  72. this.pool = pool;
  73. }
  74. public void run() {
  75. MyConnection myConn = null;
  76. try {
  77. myConn = (MyConnection)pool.borrowObject();
  78. try {
  79. myConn.print();
  80. } catch(Exception ex) {
  81. pool.invalidateObject(myConn);
  82. myConn = null;
  83. }
  84. Thread.sleep(10L * 1000L);
  85. } catch(Exception ex) {
  86. logger.error("Cannot borrow connection from pool.", ex);
  87. } finally {
  88. if (myConn != null) {
  89. try {
  90. pool.returnObject(myConn);
  91. } catch (Exception ex) {
  92. logger.error("Cannot return connection from pool.", ex);
  93. }
  94. }
  95. }
  96. }
  97. }
  98. }

其中包含了三个方法,分别测试了三种情况;

  • 类中包含了一个实现了Runnable接口的内部类,目的是为了启动几个线程来模拟的对连接类的使用,并且为了尽可能的真实,在run方法里sleep了10秒中;

  • 先运行测试方法test1()可以看到,在循环10个线程申请Connection类时,前面5个可以很好的获取,但是后面5个线程就不能获取连接,并且
    抛出了异常,这是由于“config.maxActive = 5;”和“config.maxWait = 5 *
    1000;”在起作用,由于配置了最大活动连接是5个,并且后续申请没有有效连接的等待时间是5秒,所以test1方法中后面五个线程在等了5秒后全部抛
    出异常,表明不能申请连接了。
  • 下面运行test2()方法,在test2中把“config.maxWait = 20 * 1000;”改成了20秒,而我们程序中每个线程使用连接会用去10秒,所以后面五个线程在等待了10秒后就全部获取连接了,所以程序最后会运行成功。

  • 看test3()方法,其中把maxIdle和minIdle都改为0,就是在连接不用时立即真正归还连接,对于数据库连接来说就是关闭物理连接,而
    maxWait改为-1,就是如果没有申请到连接就永远等待,运行test3()方法,观察日志,可以看出程序在用户连接对象以后,会调用
    MyConnectionPoolableObjectFactory.destroyObject()和MyConnection.close()方法
    来销毁对象。所以如果是使用这样的配置,就相当于每次都是物理连接,用完后就关闭连接。当然这里是一个极端的例子,真实情况下不会把maxIdle和
    minIdle都设为0的。

其实对于GenericObjectPool.Config类和GenericKeyedObjectPool.Config类还是有很多配置参数的,这里只是列出的最简单的几个常用的,具体可以参考官方文档。

来源:http://blog.csdn.net/kongxx/article/details/6612760

源码地址:https://github.com/apache/commons-pool

相关:开源项目剖析之apache-common-pool

commons-pool实战之 GenericObjectPool和GenericKeyedObjectPool的更多相关文章

  1. NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool

    错误:Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/pool/impl ...

  2. Spring + Tomcat 启动报错java.lang.ClassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool

    错误如下: -- ::,-[TS] INFO http-- org.springframework.beans.factory.support.DefaultListableBeanFactory - ...

  3. org/apache/commons/pool/impl/GenericObjectPool异常的解决办法

    org/apache/commons/pool/impl/GenericObjectPool异常的解决办法 webwork+spring+hibernate框架的集成, 一启动Tomcat服务器就出了 ...

  4. 对象池化技术 org.apache.commons.pool

    恰当地使用对象池化技术,可以有效地减少对象生成和初始化时的消耗,提高系统的运行效率.Jakarta Commons Pool组件提供了一整套用于实现对象池化的框架,以及若干种各具特色的对象池实现,可以 ...

  5. apache commons pool

    apache commons下的pool 其中的borrowObject函数源代码显示其产生可用对象的过程: 如果stack中有空闲的对象,则pop对象,激活对象(activate函数),验证对象(v ...

  6. Apache Commons Pool 故事一则

    Apache Commons Pool 故事一则 最近工作中遇到一个由于对commons-pool的使用不当而引发的问题,习得正确的使用姿势后,写下这个简单的故事,帮助理解Apache Commons ...

  7. 池化 - Apache Commons Pool

    对于那些创建耗时较长,或者资源占用较多的对象,比如网络连接,线程之类的资源,通常使用池化来管理这些对象,从而达到提高性能的目的.比如数据库连接池(c3p0, dbcp), java的线程池 Execu ...

  8. JedisCluster中应用的Apache Commons Pool对象池技术

    对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分.   apache common pool 官方文档可以参考:https://c ...

  9. Cache Lucene IndexReader with Apache Commons Pool

    IndexReaderFactory.java 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 2 ...

随机推荐

  1. 自定义不等高cell—storyBoard或xib自定义不等高cell

    1.iOS8之后利用storyBoard或者xib自定义不等高cell: 对比自定义等高cell,需要几个额外的步骤(iOS8开始才支持) 添加子控件和contentView(cell的content ...

  2. BZOJ 3721: PA2014 Final Bazarek

    3721: PA2014 Final Bazarek Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 645  Solved: 261[Submit][ ...

  3. 【poj3522】 Slim Span

    http://poj.org/problem?id=3522 (题目链接) 题意 求最小生成树的最大边与最小边差最小. Solution 排序后滑动窗口维护 代码 // poj3522 #includ ...

  4. 【bzoj3757】 苹果树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3757 (题目链接) MD调了好久,最后蒯了几个标程交上去,没想到都RE了...最后才看到:  = = ...

  5. MVC重写DefaultModelBinder实现自定义模型绑定

    在编写前台页面的时候为了使url传递参数的简短,比如personId="1"  我们通过url传递成pid=1  那么在后台action方法接受的模型Person类 的属性为per ...

  6. 用python来调试网络程序

    需要联调的程序,沟通联调起来总是各种麻烦,如果自己能写个简单一点的“测试机”,事情就很easy了:或者有时候想做“中间人”,看看网路上到底传些什么.前面写了串口的测试机,今天尝试了一下UDP的. im ...

  7. python——代码编码格式转换

    最近刚换工作不久,没太多的时间去整理工作中的东西,大部分时间都在用来熟悉新公司的业务,熟悉他们的代码框架了,最主要的是还有很多新东西要学,我之前主要是做php后台开发的,来这边之后还要把我半路出家的前 ...

  8. git命令笔记2

    . # 忽略所有后缀为.a的文件 *.a # 不忽略lib.a(相对于上面的) !lib.a # 只忽略根下的TODO,不递归到子目录 /TODO # 忽略所有build/下的文件 build/ # ...

  9. HDU 2544 单源最短路

    题目链接: 传送门 最短路 Time Limit: 1000MS     Memory Limit: 65536K 题目描述 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是 ...

  10. HDU 1598 find the most comfortable road(最小生成树之Kruskal)

    题目链接: 传送门 find the most comfortable road Time Limit: 1000MS     Memory Limit: 32768 K Description XX ...