Java對象池技術原理及其實現

來源:互聯網
上載者:User
■Java中對象的生命週期分析
  Java對象的生命週期大致包括三個階段:對象的建立,對象的使用,對象的清除.因此,對 象的生命週期長度可用如下的運算式表示:T = T1 + T2 +T3.其中T1表示對象的建立時間,T2表示對象的使用時間,而T3則表示其清除時間.由此,我們可以看出,只有T2是真正有效時間,而T1,T3則 是對象本身的開銷.下面再看看T1,T3在對象的整個生命週期中所佔的比例.
  我們知道,Java對象是通過建構函式來建立的,在這一 過程中,該建構函式鏈中的所有建構函式也都會被自動調用.另外,預設情況下,調用類的建構函式時,Java會把變數初始化成確定的值:所有的對象被設定成 null,整數變數(byte,short,int,long)設定成0,float和double變數設定成0.0,邏輯值設定成false.所以用 new關鍵字來建立一個對象的時間開銷是很大的,如表1所示.
表1 一些操作所耗費時間的對照表
運算操作|樣本|標準化時間
本地賦值|i = n |1.0
執行個體賦值|this.i = n|1.2
方法調用|Funct()|5.9
建立對象|New Object() |980
建立數組|New int[10] |3100
從表1可以看出,建立一個對象需要980個單位的時間,是本地賦值時間的980倍,是方法調用時間的166倍,而若建立一個數組所花費的時間就更多了.
   再看清除對象的過程.我們知道,Java語言的一個優勢,就是Java程式員勿需再像C/C++程式員那樣,顯式地釋放對象,而由稱為垃圾收集器 (Garbage Collector)的自動記憶體管理系統,定時或在記憶體凸現出不足時,自動回收垃圾對象所佔的記憶體.凡事有利總也有弊,這雖然為Java程式設計者提供了 極大的方便,但同時它也帶來了較大的效能開銷.這種開銷包括兩方面,首先是對象管理開銷,GC為了能夠正確釋放對象,它必須監控每一個對象的運行狀態,包 括對象的申請,引用,被引用,賦值等.其次,在GC開始回收"垃圾"對象時,系統會暫停應用程式的執行,而獨自佔用CPU.
  因此,如果要改善應用程式的效能,一方面應盡量減少建立新對象的次數;同時,還應盡量減少T1,T3的時間,而這些均可以通過對象池技術來實現.
對象池技術基本原理的核心有兩點:緩衝和共用,即對於那些被頻繁使用的對象,在使用完後,不立即將它們釋放,而是將它們緩衝起來,以供後續的應用程式重複 使用,從而減少建立對象和釋放對象的次數,進而改善應用程式的效能.事實上,由於對象池技術將對象限制在一定的數量,也有效地減少了應用程式記憶體上的開 銷.
實現一個對象池,一般會涉及到如下的類:
1)對象池工廠(ObjectPoolFactory)類
  該類主要用於管理相同類型和設定的對象池(ObjectPool),它一般包含如下兩個方法:
•createPool:用於建立特定類型和設定的對象池;
•destroyPool:用於釋放指定的對象池;
 同時為保證ObjectPoolFactory的單一執行個體,可以採用Singleton設計模式,見下述getInstance方法的實現:
public static ObjectPoolFactory getInstance() {
 if (poolFactory == null) {
  poolFactory = new ObjectPoolFactory();
 }
 return poolFactory;
}
2)參數對象(ParameterObject)類
 該類主要用於封裝所建立對象池的一些屬性參數,如池中可存放對象的數目的最大值(maxCount),最小值(minCount)等.
3)對象池(ObjectPool)類
用於管理要被池化對象的借出和歸還,並通知PoolableObjectFactory完成相應的工作.它一般包含如下兩個方法:
•getObject:用於從池中借出對象;
•returnObject:將池化對象返回到池中,並通知所有處於等待狀態的線程;
4)池化對象工廠(PoolableObjectFactory)類
  該類主要負責管理池化對象的生命週期,就簡單來說,一般包括對象的建立及銷毀.該類同ObjectPoolFactory一樣,也可將其實現為單一實例.
通用對象池的實現
  對象池的構造和管理可以按照多種方式實現.最靈活的方式是將池化對象的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類的同步操作,使得它在某些情況下對效能的改進非常有限,尤其對那些建立周期比較短的對象.
■專用對象池的實現     
  由於通用對象池的管理開銷比較大,某種程度上抵消了重用對象所 帶來的大部分優勢.為解決該問題,可以採用專用對象池的方法.即對象池所池化對象的Class類型不是動態指定的,而是預先就已指定.這樣,它在實現上也 會較通用對象池簡單些,可以不要ObjectPoolFactory和PoolableObjectFactory類,而將它們的功能直接融合到 ObjectPool類,具體如下(假定被池化對象的Class類型仍為StringBuffer,而用省略符號表示的地方,表示代碼同通用對象池的實 現):
public class ObjectPool {
 private ParameterObject paraObj;//該對象池的屬性參數對象
 private int currentNum = 0; //該對象池當前已建立的對象數目
 private StringBuffer currentObj;//該對象池當前可以借出的對象
 private Vector pool;//用於存放對象的池
 public ObjectPool(ParameterObject paraObj) {
  this.paraObj = paraObj;
  pool = new Vector();
 }
 public StringBuffer getObject() {
  if (pool.size() <= paraObj.getMinCount()) {
   if (currentNum <= paraObj.getMaxCount()) {
    currentObj = new StringBuffer();
    currentNum++;
   }
   . . .
  }
  return currentObj;
 }
 public void returnObject(Object obj) {
  // 確保對象具有正確的類型
  if (StringBuffer.isInstance(obj)) {
   . . .
  }
 }
結束語
1.恰當地使用對象池技術,能有效地改善應用程式的效能.目前,對象池技術已得到廣泛的應用,如對於網路和資料庫連接這類重量級的對象,一般都會採用對象池技術.但在使用對象池技術時也要注意如下問題:
2.並非任何情況下都適合採用對象池技術.基本上,只在重複產生某種對象的操作成為影響效能的關鍵因素的時候,才適合採用對象池技術.而如果進行池化所能帶來的效能提高並不重要的話,還是不採用對象池化技術為佳,以保持代碼的簡明.
3.要根據具體情況正確選擇對象池的實現方式.如果是建立一個公用的對象池技術實現包,或需要在程式中動態指定所池化對象的Class類型時,才選擇通用對象池.而大部分情況下,採用專用對象池就可以了. 
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.