J2EE系統優化的幾點體會(一、物件)

herrapfel發表於2005-06-15

說到系統優化,是一個比較複雜的問題,涉及到軟體的各個方面:需求、模組劃分、資料庫設計、程式編碼以及一些特殊的優化方法如快取技術等。而不同的應用又有其特殊的優化策略和技術。同時優化是貫穿系統從需求到實現再到維護的各個階段的一項活動,而在各個階段又有其不同的著眼點和具體方法。
本文立足於具體的J2EE專案實踐,結合一些已有的優化條例,提出自己的一些體會,也算是作為一次對實際專案經驗教訓的總結。
優化一般意義上說是提高已有系統的效能,減少如記憶體、資料庫、網路頻寬等資源的佔用,是在系統開發告一段落的前提下進行。一般是通過壓力測試或具體使用發現效能方面的問題,然後尋找效能瓶頸,並結合專案進度、人員安排、技術儲備等因素,提出相應的優化策略。
下面結合一些案例,進行具體的討論,並希望能總結出一些具有代表性的條例:

條例一:儘量重用物件,避免建立過多短時物件

物件在物件導向程式設計中隨處可見,甚至可以毫不誇張的說是:“一切都是物件”。如何更好的建立和使用物件,是優化中要考慮的一個重要方面。筆者將物件按使用分為兩大類:獨享物件和共享物件。獨享物件指由某個執行緒單獨擁有並維護其生命週期的物件,一般是通過new 建立的物件,執行緒結束且無其它對這個物件的引用,這個物件將由垃圾收集機制自動GC。共享物件指由多個執行緒共享的物件,各執行緒保持多個指向同一個物件的引用,任何對這個物件的修改都會在其它引用上得到體現,共享物件一般通過Factory工廠的getInstace()方法建立,單例模式就是建立共享物件的標準實現。獨享物件由於無其它指向同一物件的引用,不用擔心其它引用對物件屬性的修改,在多執行緒環境裡,也就不需要對其可能修改屬性的方法加以同步,減少了出錯的隱患和複雜性,但由於需要為每個執行緒都建立物件,增加了對記憶體的需求和JVM GC的負擔。共享物件則需要進行適當的同步(避免較大的同步塊,同時防止死鎖)。
還有幾種特殊物件:不變物件和方法物件。不變物件指物件對外不含有修改物件屬性的方法(如set方法),外部要修改屬性只能通過new新的例項來實現。不變物件最大的好處就是無需擔心屬性被修改,避免了潛在的bug,並能無需任何額外工作(如同步)就很好的工作在多執行緒環境下。如jdk的String物件就是典型的不變物件。方法物件簡單的說就是僅包含方法,不含有屬性的物件。由於沒有物件屬性,方法中無需進行修改屬性的操作,也就能採用static方法或單例模式,避免每次使用都要new物件,減少物件的使用。
那麼該如何確定建立何種物件,這就要結合物件的使用方式和生命週期、物件大小、構建花銷等方面來綜合考慮。如果物件生命週期較長,會存在修改操作,不能容忍其它執行緒對其的修改,就應該採用獨享物件,如常見的Bean類。而如果物件生命週期較長,且能為各個執行緒共享,就可以考慮共享物件。共享有2種常見情況,一種是系統全域性物件,如配置屬性等,各個執行緒應該引用同一物件,任何對這個物件的修改都會影響其它執行緒;另一種是由於物件建立開銷較大,各執行緒對此物件是瞬時訪問,且無需再次讀取其屬性,如常見的Date 物件,一般這種物件的使用是瞬時的,比如把它format成String,如果每次建立然後等待GC就會浪費大量記憶體和CPU時間,較好做法就是做成共享物件,各個執行緒先set再使用,注意對進行set並訪問的方法要同步。不變物件一般使用在物件建立開銷較小(屬性較少,類層次較少),且需要能自由共享的情形。如一個物件裡的常量物件,使用public static final AAA=new AAA(…) 建立。方法物件使用較廣,如Util類、DAO類等,這些物件提供操作其它物件(一般是bean物件)的介面,能對系統在層次和功能上進行解耦合。

相關文章