對象池使用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類仍是有不少配置參數的,這裏只是列出的最簡單的幾個經常使用的,具體能夠參考官方文檔。

相關文章
相關標籤/搜索