前面两篇文章说了怎么样简单的使用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. shell 常用小命令总结

      1. 重命名 1) 较简单的处理命令:mv 原文件名 新文件名 如:mv myFile newName                           ###  将MyFile重命名为newN ...

  2. css-a与a:link的一些认识

    1.a元素有四种状态: a:link {color:blue;}//未点击的链接状态 a:visited {color:blue;}//已点击的连接状态 a:hover {color:red;}//鼠 ...

  3. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

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

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

  5. C# .NET 使用第三方类库DotNetZip解压/压缩Zip文件

    dotNetZip on CodePlex: http://dotnetzip.codeplex.com/ 详细的可以看源代码……总之感觉比SharpZipLib好用.而且DotNetZip支持VB, ...

  6. HDU2203 亲和串

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  7. css中import与link用法区别

    方式:引入CSS的方法有两种,一种是@import,一种是link @import url('地址');//注意,这种方式可以放在页面也可以放在css文件中<link href="地址 ...

  8. Linux文件系统介绍(转)

    文章转自:http://www.iteye.com/topic/816268 文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文 ...

  9. windows核心编程读后感(待续)

    自从大一读那本超厚的C程序设计以后,从来没有像这样慢慢地读一本书了.windows核心这本书足足看了2个多星期.一张张慢慢看,做笔记.感觉学到了很多基础的知识,关于内核方面的没有啥可以做实验的,都在看 ...

  10. 关于 htonl 和 ntohl 的实现

    因为需要直接处理一个网络字节序的 32 位 int,所以,考虑用自己写的还是系统函数效率更高.然后又了下面的了解. 首先是系统函数 htonl ,我在 kernel 源码 netinet/in.h 找 ...