对象池使用commons-pool实战之 GenericObjectPool和GenericKeye

一个Connection类,能够想象成一个远程链接好比数据库链接等。其中包括建立链接,关闭链接,和一个print方法。
java

[java] view plaincopyprint?数据库

  1. package com.googlecode.garbagecan.commons.pool.sample3;  apache

  2.   

  3. import org.slf4j.Logger;  测试

  4. import org.slf4j.LoggerFactory;  this

  5.   

  6. public class MyConnection {  google

  7.       

  8.     private static Logger logger = LoggerFactory.getLogger(MyConnection.class);  spa

  9.       

  10.     private String name;  .net

  11.     private boolean connected;  线程

  12.   

  13.     public MyConnection(String name) {  日志

  14.         this.name = name;  

  15.     }  

  16.   

  17.     public void connect() {  

  18.         this.connected = true;  

  19.         logger.info(name + ": " + connected);  

  20.     }  

  21.   

  22.     public void close() {  

  23.         this.connected = false;  

  24.         logger.info(name + ": " + connected);  

  25.     }  

  26.   

  27.     public boolean isConnected() {  

  28.         return this.connected;  

  29.     }  

  30.       

  31.     public String getName() {  

  32.         return this.name;  

  33.     }  

  34.       

  35.     public void print() {  

  36.         logger.info(this.name);  

  37.     }  

  38. }  

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

[java] view plaincopyprint?

  1. package com.googlecode.garbagecan.commons.pool.sample3;  

  2.   

  3. import org.apache.commons.pool.PoolableObjectFactory;  

  4. import org.slf4j.Logger;  

  5. import org.slf4j.LoggerFactory;  

  6.   

  7. public class MyConnectionPoolableObjectFactory implements PoolableObjectFactory {  

  8.   

  9.     private static Logger logger = LoggerFactory.getLogger(MyConnectionPoolableObjectFactory.class);  

  10.       

  11.     private static int count = 0;  

  12.       

  13.     public Object makeObject() throws Exception {  

  14.         MyConnection myConn = new MyConnection(generateName());  

  15.         logger.info(myConn.getName());  

  16.         myConn.connect();  

  17.         return myConn;  

  18.     }  

  19.       

  20.     public void activateObject(Object obj) throws Exception {  

  21.         MyConnection myConn = (MyConnection)obj;  

  22.         logger.info(myConn.getName());  

  23.     }  

  24.   

  25.     public void passivateObject(Object obj) throws Exception {  

  26.         MyConnection myConn = (MyConnection)obj;  

  27.         logger.info(myConn.getName());  

  28.     }  

  29.       

  30.     public boolean validateObject(Object obj) {  

  31.         MyConnection myConn = (MyConnection)obj;  

  32.         logger.info(myConn.getName());  

  33.         return myConn.isConnected();  

  34.     }  

  35.       

  36.     public void destroyObject(Object obj) throws Exception {  

  37.         MyConnection myConn = (MyConnection)obj;  

  38.         logger.info(myConn.getName());  

  39.         myConn.close();  

  40.     }  

  41.       

  42.     private synchronized String generateName() {  

  43.         return "conn_" + (++count);  

  44.     }  

  45. }  

一个测试类

[java] view plaincopyprint?

  1. package com.googlecode.garbagecan.commons.pool.sample3;  

  2.   

  3. import org.apache.commons.pool.ObjectPool;  

  4. import org.apache.commons.pool.PoolableObjectFactory;  

  5. import org.apache.commons.pool.impl.GenericObjectPool;  

  6. import org.slf4j.Logger;  

  7. import org.slf4j.LoggerFactory;  

  8.   

  9. public class Test {  

  10.       

  11.     private static Logger logger = LoggerFactory.getLogger(Test.class);  

  12.       

  13.     public static void main(String[] args) {  

  14.         //test1();  

  15.         //test2();  

  16.         //test3();  

  17.     }  

  18.       

  19.     private static void test1() {  

  20.         PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();  

  21.         GenericObjectPool.Config config = new GenericObjectPool.Config();  

  22.         config.lifo = false;  

  23.         config.maxActive = 5;  

  24.         config.maxIdle = 5;  

  25.         config.minIdle = 1;  

  26.         config.maxWait = 5 * 1000;  

  27.           

  28.         ObjectPool pool = new GenericObjectPool(factory, config);  

  29.         for (int i = 0; i < 10; i++) {  

  30.             Thread thread = new Thread(new MyTask(pool));  

  31.             thread.start();  

  32.         }  

  33.         //closePool(pool);  

  34.     }  

  35.       

  36.     private static void test2() {  

  37.         PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();  

  38.         GenericObjectPool.Config config = new GenericObjectPool.Config();  

  39.         config.lifo = false;  

  40.         config.maxActive = 5;  

  41.         config.maxIdle = 5;  

  42.         config.minIdle = 1;  

  43.         config.maxWait = 20 * 1000;  

  44.   

  45.         ObjectPool pool = new GenericObjectPool(factory, config);  

  46.         for (int i = 0; i < 10; i++) {  

  47.             Thread thread = new Thread(new MyTask(pool));  

  48.             thread.start();  

  49.         }  

  50.         //closePool(pool);  

  51.     }  

  52.   

  53.     private static void test3() {  

  54.         PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();  

  55.         GenericObjectPool.Config config = new GenericObjectPool.Config();  

  56.         config.lifo = false;  

  57.         config.maxActive = 5;  

  58.         config.maxIdle = 0;  

  59.         config.minIdle = 0;  

  60.         config.maxWait = -1;  

  61.   

  62.         ObjectPool pool = new GenericObjectPool(factory, config);  

  63.         Thread thread = new Thread(new MyTask(pool));  

  64.         thread.start();  

  65.   

  66.         try {  

  67.             Thread.sleep(60L * 1000L);  

  68.         } catch (Exception e) {  

  69.             e.printStackTrace();  

  70.         }  

  71.           

  72.         //closePool(pool);  

  73.     }  

  74.   

  75.     private static void closePool(ObjectPool pool) {  

  76.         try {  

  77.             pool.close();  

  78.         } catch (Exception e) {  

  79.             e.printStackTrace();  

  80.         }  

  81.     }  

  82.       

  83.     private static class MyTask implements Runnable {  

  84.         private ObjectPool pool;  

  85.           

  86.         public MyTask(ObjectPool pool) {  

  87.             this.pool = pool;  

  88.         }  

  89.           

  90.         public void run() {  

  91.             MyConnection myConn = null;  

  92.             try {  

  93.                 myConn = (MyConnection)pool.borrowObject();  

  94.                 try {  

  95.                     myConn.print();  

  96.                 } catch(Exception ex) {  

  97.                     pool.invalidateObject(myConn);  

  98.                     myConn = null;  

  99.                 }  

  100.                 Thread.sleep(10L * 1000L);  

  101.             } catch(Exception ex) {  

  102.                 logger.error("Cannot borrow connection from pool.", ex);  

  103.             } finally {  

  104.                 if (myConn != null) {  

  105.                     try {  

  106.                         pool.returnObject(myConn);  

  107.                     } catch (Exception ex) {  

  108.                         logger.error("Cannot return connection from pool.", ex);  

  109.                     }  

  110.                 }  

  111.             }  

  112.         }  

  113.     }  

  114. }  

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

  • 类中包含了一个实现了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类仍是有不少配置参数的,这里只是列出的最简单的几个经常使用的,具体能够参考官方文档。

相关文章
相关标签/搜索