對象池commons-pool框架的研究以及源代碼分析(一)

    對象池是一個對象集合,用於將創建好的對象存在該集合中,當需要使用池中的對象時,再從池中取出,恰當地使用對象池可以有效減少對象生成和初始化時的消耗,提高系統的運行效率。另外,利用對象池還可以對對象的狀態做一定的維護,確保對象是可用的,提高程序的健壯性。注意:對象池技術,在用於一些創建需要佔用大量時間上的對象特別明顯,在一些小對象處理上,性能不一定有優勢。

Common Pool組件提供了一整套實現對象池化的框架,而且是線程安全的,我們可以不用自己花大量的精力編寫代碼就可以使用對象池對對象的管理。抱着先使用再分析,最後研究源代碼的原則,我們先看第一個例子:

首先建立一個簡單的User類,用於生成對象:

public class User
{
private int id;
private String userName;

 
public User(int id, String userName) {
super();
this.id = id;
this.userName = userName;
}
public User( ) {
 
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String toString(){
return "user id is:"+id+",userName:"+userName;
}
}

核心代碼來了,建立一個對象狀態管理工廠,用於對對象狀態的維護:

/**
* 這個類主要負責對我們的對象進行管理,由我們自己創建、激活等
* 實際使用中,我們將這個類傳遞給對象池,由對象池調用我們自己編寫的代碼進行管理
* @author Administrator
*
*/
public class UserFactory implements PoolableObjectFactory{
//激活對象
public void activateObject(Object obj) throws Exception {
// TODO Auto-generated method stub
System.out.println("activateObject");
}
/**
* 銷燬對象,注意調用了這個方法之後,對象被銷燬,但對象池還有這個對象
*/
public void destroyObject(Object obj) throws Exception {
  System.out.println("destroyObject" );  
        //對對象進行銷燬,我們暫時將對象設置爲NULL
  obj = null;
 //如果是數據庫的連接池,可以將conn設置爲close

}
/**
* 創建對象
*/
public Object makeObject() throws Exception {
// TODO Auto-generated method stub
return new User();
}
/**
* 歸還對象後調用的方法
*/
public void passivateObject(Object obj) throws Exception {
  System.out.println("對象已經被歸還" );  
  //如果是數據庫連接池,可以設置爲提交連接

}
/**
* 驗證對象使用可用
*/
public boolean validateObject(Object obj) {
//我們這個簡單的user類好像作用不大,但如果是數據庫連接池,可以讓其執行SELECT 1 來驗證數據庫連接是否可用
 System.out.println("驗證一下對象是否可用" );  
return true;
}

}

//再編寫一個方法,來測試使用連接池情況

public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
UserFactory userFactory = new commonPool().new UserFactory();//內部類的實例化方法,代碼的可讀性不強
ObjectPool objectPool = new StackObjectPool(userFactory);
User user = (User)objectPool.borrowObject();
user.setId(1);
user.setUserName("testnam3");
System.out.println(user);
objectPool.returnObject(user);
//-----------------------------歸還後再借對象
User user2 = (User)objectPool.borrowObject();
System.out.println(user2);

}

從代碼中可以看出,首先建立一個對象維護工廠UserFactory來維護對象的狀態,這種做法在設計上非常值得學習,對對象的維護,仍然由我們自己編寫代碼維護,因爲對象的複雜性,由我們自己將維護的代碼傳遞給對象池,由對象池調用我們的對象維護實例對對象進行維護,在設計上相當精妙,今後我們在軟件開發中,需要學習它這種設計方式。

創建完對象維護工廠後,就可以創建一個對象池,然後調用對象池的方法獲取對象或歸還對象,從代碼中可以看出,ObjectPool 是一個接口,我們來看看這個接口包括了哪些方法:


 Object borrowObject() throws Exception;//從對象池中獲取對象
    void returnObject(Object obj) throws Exception;//將對象還給對象池
    void invalidateObject(Object obj) throws Exception;//將對象設置爲無效
    void addObject() throws Exception;//添加對象
    int getNumIdle() throws UnsupportedOperationException;//獲取空閒對象數目
    int getNumActive() throws UnsupportedOperationException;//獲取正在使用的對象數目
    void clear() throws Exception, UnsupportedOperationException;//清除空閒對象
    void close() throws Exception;//關閉對象池並釋放對象資源
    void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException;//設置對象狀態維護工廠

實際上,與我們接觸最多的兩個接口,就是對象狀態維護工廠以及對象池接口,下面我們再看看代碼執行結果:

activateObject
驗證一下對象是否可用
user id is:1,userName:testnam3
驗證一下對象是否可用
對象已經被歸還
activateObject
驗證一下對象是否可用
user id is:1,userName:testnam3

從結果我們可以看出,對象歸還後,並沒有銷燬掉,而是存放在池中,當我們重新獲取對象時,又從池中取出。另外,對象池調用在借用對象、歸還對象時,對象池自動調用了對象驗證的方法,是否需要驗證,可以通過配置來實現,後面代碼中再具體分析。


特別提出:使用對象池時,借用對象,必須歸還,所謂有借有還,下次再借不難,上面的演示代碼,最後一次借用對象後沒有歸還,在實際應用中,這種做法是不可取的。















發佈了41 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章