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

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

[java] view plaincopyprint?

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

  2.   

  3. import org.slf4j.Logger;  

  4. import org.slf4j.LoggerFactory;  

  5.   

  6. public class MyConnection {  

  7.       

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

  9.       

  10.     private String name;  

  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类还是有很多配置参数的,这里只是列出的最简单的几个常用的,具体可以参考官方文档。


你可能感兴趣的:(对象池使用commons-pool实战之 GenericObjectPool和GenericKeye)