前面两篇文章说了怎么样简单的使用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 1112】Team Them Up!(二分图染色+DP)

    Description Your task is to divide a number of persons into two teams, in such a way, that: everyone ...

  2. 新版汉诺塔(UVa10795 - A Different Task)

    题目介绍: 标准的汉诺塔上有n个大小各异的盘子.现给定一个初始局面(见图1),求它到目标局面(见图2)至少需要移动多少步? 移动规则:一次只能移动一个盘子:且在移动盘子之前,必须把压在上面的其他盘子先 ...

  3. Anroid Studio入门

    转载:http://www.apkbus.com/forum.php?mod=viewthread&tid=255186&extra=page%3D1%26filter%3Dautho ...

  4. Top K 问题

    Example Given [3,10,1000,-99,4,100] and k = 3. Return [1000, 100, 10]. 解法有以下几种: 1. bubble sort k tim ...

  5. 【poj1018】 Communication System

    http://poj.org/problem?id=1018 (题目链接) 题意 要买n个产品,每个产品有m种价格和宽度(我也不知道翻译过来到底是什么?),设n个产品的宽度的最小值为B,n个产品的价格 ...

  6. BZOJ2426 [HAOI2010]工厂选址

    Description 某地区有m座煤矿,其中第i号矿每年产量为ai吨,现有火力发电厂一个,每年需用煤b吨,每年运行的固定费用(包括折旧费,不包括煤的运费)为h元,每吨原煤从第i号矿运到原有发电厂的运 ...

  7. hdu 5147 树状数组

    题意:求满足a<b<c<d,A[a]<A[b],A[c]<A[d]的所有四元组(a,b,c,d)的个数 看到逆序对顺序对之类的问题一开始想到了曾经用归并排序求逆序对,结果 ...

  8. Linux System Account SSH Weak Password Detection Automatic By System API

    catalog . Linux弱口令攻击向量 . Linux登录验证步骤 . PAM . 弱口令风险基线检查 1. Linux弱口令攻击向量 0x1: SSH密码暴力破解 hydra -l root ...

  9. Akka: actor应用的一些小结

    1.消息: 1) case class是scala中一个不可变对象(当然你可以让他成为可变的),通过不可变对象来进行消息传递可以更加明确内容,也能保证线程安全 2) 在Java中如果你将class对象 ...

  10. [Android]Volley的使用

    Volley是Google I/O 2013上提出来的为Android提供简单快速网络访问的项目.Volley特别适合数据量不大但是通信频繁的场景. 优势 相比其他网络载入类库,Volley 的优势官 ...