设计模式--对象池

来源:互联网 发布:字符数组的定义 编辑:程序博客网 时间:2024/04/27 23:20
定义
一个对象池是一组已经初始化过且可以使用的对象的集合,池的用户可以从池子中取得对象,对其进行操作处理,并在不需要时归还给池子而非销毁它。

若初始化、实例化的代价高,且有需求需要经常实例化,但每次实例化的数量较少的情况下,使用对象池可以获得显著的效能提升。从池子中取得对象的时间是可预测的,但新建一个实例所需的时间是不确定。

实现

1. Reusable - 对象池中的对象,通常实例化代价比较高。
2. Client - 使用一个对象的实例。
3. ReusablePool - 管理对象的实例化,回收和销毁。
[java] view plaincopy
  1. // ObjectPool Class  
  2. public abstract class ObjectPool<T> {  
  3.   private long expirationTime;  
  4.   
  5.   private Hashtable<T, Long> locked, unlocked;  
  6.   
  7.   public ObjectPool() {  
  8.     expirationTime = 30000// 30 seconds  
  9.     locked = new Hashtable<T, Long>();  
  10.     unlocked = new Hashtable<T, Long>();  
  11.   }  
  12.   
  13.   protected abstract T create();  
  14.   
  15.   public abstract boolean validate(T o);  
  16.   
  17.   public abstract void expire(T o);  
  18.   
  19.   public synchronized T checkOut() {  
  20.     long now = System.currentTimeMillis();  
  21.     T t;  
  22.     if (unlocked.size() > 0) {  
  23.       Enumeration<T> e = unlocked.keys();  
  24.       while (e.hasMoreElements()) {  
  25.         t = e.nextElement();  
  26.         if ((now - unlocked.get(t)) > expirationTime) {  
  27.           // object has expired 对象过期  
  28.           unlocked.remove(t);  
  29.           expire(t);  
  30.           t = null;  
  31.         } else {  
  32.           if (validate(t)) {  
  33.             unlocked.remove(t);  
  34.             locked.put(t, now);  
  35.             return (t);  
  36.           } else {  
  37.             // object failed validation 对象不生效  
  38.             unlocked.remove(t);  
  39.             expire(t);  
  40.             t = null;  
  41.           }  
  42.         }  
  43.       }  
  44.     }  
  45.     // no objects available, create a new one  
  46.     t = create();  
  47.     locked.put(t, now);  
  48.     return (t);  
  49.   }  
  50.   
  51.   public synchronized void checkIn(T t) {  
  52.     locked.remove(t);  
  53.     unlocked.put(t, System.currentTimeMillis());  
  54.   }  
  55. }  
  56.   
  57. //The three remaining methods are abstract   
  58. //and therefore must be implemented by the subclass  
  59.   
  60. public class JDBCConnectionPool extends ObjectPool<Connection> {  
  61.   
  62.   private String dsn, usr, pwd;  
  63.   
  64.   public JDBCConnectionPool(String driver, String dsn, String usr, String pwd) {  
  65.     super();  
  66.     try {  
  67.       Class.forName(driver).newInstance();  
  68.     } catch (Exception e) {  
  69.       e.printStackTrace();  
  70.     }  
  71.     this.dsn = dsn;  
  72.     this.usr = usr;  
  73.     this.pwd = pwd;  
  74.   }  
  75.   
  76.   @Override  
  77.   protected Connection create() {  
  78.     try {  
  79.       return (DriverManager.getConnection(dsn, usr, pwd));  
  80.     } catch (SQLException e) {  
  81.       e.printStackTrace();  
  82.       return (null);  
  83.     }  
  84.   }  
  85.   
  86.   @Override  
  87.   public void expire(Connection o) {  
  88.     try {  
  89.       ((Connection) o).close();  
  90.     } catch (SQLException e) {  
  91.       e.printStackTrace();  
  92.     }  
  93.   }  
  94.   
  95.   @Override  
  96.   public boolean validate(Connection o) {  
  97.     try {  
  98.       return (!((Connection) o).isClosed());  
  99.     } catch (SQLException e) {  
  100.       e.printStackTrace();  
  101.       return (false);  
  102.     }  
  103.   }  
  104. }  
  105.   
  106. public class Main {  
  107.   public static void main(String args[]) {  
  108.     // Do something...  
  109.     ...  
  110.   
  111.     // Create the ConnectionPool:  
  112.     JDBCConnectionPool pool = new JDBCConnectionPool(  
  113.       "org.hsqldb.jdbcDriver""jdbc:hsqldb://localhost/mydb",  
  114.       "sa""secret");  
  115.   
  116.     // Get a connection:  
  117.     Connection con = pool.checkOut();  
  118.   
  119.     // Use the connection  
  120.     ...  
  121.   
  122.     // Return the connection:  
  123.     pool.checkIn(con);  
  124.    
  125.   }  
  126. }  

相关问题和实现
1. 对象池中可以限制对象的个数,当超过限制时,对象池需要返回异常或者空值,以通知客户。
2. 在多线程环境中,在checkout和checkin方法需要同步。
3. 定时清理过期的对象。

参考
http://sourcemaking.com/design_patterns/object_pool
http://www.oodesign.com/object-pool-pattern.html
http://zh.wikipedia.org/wiki/%E5%AF%B9%E8%B1%A1%E6%B1%A0%E6%A8%A1%E5%BC%8F
0 0