前面两篇文章说了怎么样简单的使用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. 【POJ 1698】Alice's Chance(二分图多重匹配)

    http://poj.org/problem?id=1698 电影和日子匹配,电影可以匹配多个日子. 最多有maxw*7个日子. 二分图多重匹配完,检查一下是否每个电影都匹配了要求的日子那么多. #i ...

  2. 【USACO 2.2】Subset Sums (DP)

    N (1 <= N <= 39),问有多少种把1到N划分为两个集合的方法使得两个集合的和相等. 如果总和为奇数,那么就是0种划分方案.否则用dp做. dp[i][j]表示前 i 个数划分到 ...

  3. 58. Android一些开发习惯总结

    作者:漫步 链接:https://www.zhihu.com/question/27227425/answer/35973793 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

  4. 【caffe】cifar10例子之quick_train.sh在windows下的解决方案

    @tags caffe 照例还是转写为python脚本: import os caffe_root=os.environ['caffe_root'] caffe_build=os.environ['c ...

  5. Servlet —— 避免Servlet的并发同步问题

    Servlet的生命周期是由Servlet容器来负责的. Servlet容器通常采用单实例多线程的方式,减少Servlet创建实例的开销,提高效率. 当客户端第一次请求某个Servlet时,Servl ...

  6. 屠蛟之路_集木成舟_ForthDay

    下数据库大山,行数里至水岸,无边无际的东海便豁然展现在屠蛟少年的眼前. 要想到达东海之中的蛟灵岛绞杀beta怪蛟,夺回心爱的小公举,少年们首先需要一艘经得起风浪的船.毕竟海上之路暗涌潜伏.同样凶险万分 ...

  7. 【Beta】第二次任务发布

    后端 了解社区新建文章.添加评论(回复)的机制.整理成API文档,包括如何请求新建文章.新建评论(回复).如何获取文章内容和评论内容. 验收条件:文档PM要能看懂. 前端 微调数据输入部分的布局和操作 ...

  8. POJ 2942Knights of the Round Table(二分图判定+双连通分量)

    题目链接 题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件:1.人数大于1.2.总人数为奇数.3.有仇恨的骑士不能挨着坐.问有几个骑士不能和任何人形成任何的圆圈. ...

  9. C#调用WebService实现天气预报

    http://zhangkui.blog.51cto.com/1796259/497324/ 本文使用Winform (C#)调用互联网上公开的WebServices(http://www.webxm ...

  10. log4net详解(转载)

    1.概述 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是介绍如何在Visual S ...