通用對象池的實現
對象池的構造和管理可以按照多種方式實現。最靈活的方式是將池化對象的Class類型在對象池之外指定,即在ObjectPoolFactory類建立對象池時,動態指定該對象池所池化對象的Class類型,其實現代碼如下:
. . . public ObjectPool createPool(ParameterObject paraObj,Class clsType) { return new ObjectPool(paraObj, clsType); } . . . |
其中,paraObj參數用於指定對象池的特徵屬性,clsType參數則指定了該對象池所存放對象的類型。對象池(ObjectPool)建立以後,下面就是利用它來管理對象了,具體實現如下:
public class ObjectPool { private ParameterObject paraObj;//該對象池的屬性參數對象 private Class clsType;//該對象池中所存放對象的類型 private int currentNum = 0; //該對象池當前已建立的對象數目 private Object currentObj;//該對象池當前可以借出的對象 private Vector pool;//用於存放對象的池 public ObjectPool(ParameterObject paraObj, Class clsType) { this.paraObj = paraObj; this.clsType = clsType; pool = new Vector(); } public Object getObject() { if (pool.size() <= paraObj.getMinCount()) { if (currentNum <= paraObj.getMaxCount()) { //如果當前池中無對象可用,而且已建立的對象數目小於所限制的最大值,就利用 //PoolObjectFactory建立一個新的對象 PoolableObjectFactory objFactory =PoolableObjectFactory.getInstance(); currentObj = objFactory.create Object (clsType); currentNum++; } else { //如果當前池中無對象可用,而且所建立的對象數目已達到所限制的最大值, //就只能等待其它線程返回對象到池中 synchronized (this) { try { wait(); } catch (InterruptedException e) { System.out.println(e.getMessage()); e.printStackTrace(); } currentObj = pool.firstElement(); } } } else { //如果當前池中有可用的對象,就直接從池中取出對象 currentObj = pool.firstElement(); } return currentObj; } public void returnObject(Object obj) { // 確保對象具有正確的類型 if (obj.isInstance(clsType)) { pool.addElement(obj); synchronized (this) { notifyAll(); } } else { throw new IllegalArgumentException("該對象池不能存放指定的物件類型"); } } } |
從上述代碼可以看出,ObjectPool利用一個java.util.Vector作為可擴充的對象池,並通過它的建構函式來指定池化對象的Class類型及對象池的一些屬性。在有對象返回到對象池時,它將檢查對象的類型是否正確。當對象池裡不再有可用對象時,它或者等待已被使用的池化對象返回池中,或者建立一個新的對象執行個體。不過,新對象執行個體的建立並不在ObjectPool類中,而是由PoolableObjectFactory類的createObject方法來完成的,具體實現如下:
. . . public Object createObject(Class clsType) { Object obj = null; try { obj = clsType.newInstance(); } catch (Exception e) { e.printStackTrace(); } return obj; } . . . |
這樣,通用對象池的實現就算完成了,下面再看看用戶端(Client)如何來使用它,假定池化對象的Class類型為StringBuffer:
. . . //建立對象池工廠 ObjectPoolFactory poolFactory = ObjectPoolFactory. getInstance (); //定義所建立對象池的屬性 ParameterObject paraObj = new ParameterObject(2,1); //利用對象池工廠,建立一個存放StringBuffer類型對象的對象池 ObjectPool pool = poolFactory.createPool(paraObj,String Buffer.class); //從池中取出一個StringBuffer對象 StringBuffer buffer = (StringBuffer)pool.getObject(); //使用從池中取出的StringBuffer對象 buffer.append("hello"); System.out.println(buffer.toString()); . . . |
可以看出,通用對象池使用起來還是很方便的,不僅可以方便地避免頻繁建立對象的開銷,而且通用程度高。但遺憾的是,由於需要使用大量的類型定型(cast)操作,再加上一些對Vector類的同步操作,使得它在某些情況下對效能的改進非常有限,尤其對那些建立周期比較短的對象。