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對象)的接口,能對系統在層次和功能上進行解耦合。
條例二:在循環處,多下功夫
循環作爲程序編寫的基本語法,可以說是隨處可見。一些小的細節能帶來性能上的提升,而對循環體的一些改寫,能帶來性能的大幅提升。
比如最簡單的List遍歷,會有這樣的寫法:for(int i=0;i
同樣是對List的'操作,如果要在遍歷同時進行增加和刪除操作,代碼如下:for(int i=0,j=();i=0;i--){ve(i);}。經過測試,如果採用ArrayList,兩種寫法在循環次數較少時沒有太大的區別,循環次數爲1000,均爲1ms以內,次數爲10000,前一種爲60ms左右,後一種爲1ms以內,,而次數上到100000,前一種爲6000ms左右,後一種爲15ms,隨着循環次數的增多,後一種較前一種的效率優勢明顯提高。
這是由Collection庫ArrayList的實現決定的,以下是jdk1.3的ArrayList源碼:
從中我們可以看出,numMoved代表了需要進行arraycopy操作的數量,它是由remove的位置決定的,如果index=0,也就是刪除第一個元素,則需要arraycopy後面的所有數據,而如果index=size-1,則只需將最後一個元素設爲null即可。所以從後面向前循環remove是比較好的寫法。
如果List中的確存在較多的add或remove操作,且容量較大(如存儲幾萬個對象),則應該採用LinkedList作爲實現。LinkedList內部採用雙向鏈表作爲數據結構,比ArrayList佔用較多內存空間,且隨機訪問操作較慢(需要從頭或尾循環到相應位置),但插入刪除操作很快(僅需進行鏈表操作,無須大量移動或拷貝)。
對於List操作如果循環規模較小,其實對性能影響非常小(ms級),遠遠不是性能瓶頸所在。但心中有着優化的意識,併力求寫出簡潔高效的程序應該是我們每個程序員的追求。而且一旦在循環規模較大時,如果有了這些意識,也就能有效的消除性能隱患。
再舉一個與優化無關但確實可能成爲性能殺手(可以說是bug)的循環的例子。下面是源代碼:
這個代碼意圖很清楚,就是將一個InputStream流讀到一個byte數組中去。它使用read方法循環讀取InputStream,該方法返回讀取的字節數。正常情況下,該循環運行良好,當totalRead=m_totalBytes時,結束循環,byte數組被正常填充。但如果仔細看一下InputStream的read方法的說明,瞭解一下其返回值就會發現,返回值可能爲-1,即已讀到InputStream末尾再繼續讀時。如果發生讀取異常,可能出現這個問題,而這個循環沒有檢查readBytes值是否爲-1就往totalRead上加,這樣再次進入循環體繼續讀取InputStream,又返回-1,繼續循環。如此循環直到int溢出纔會跳出循環。而這個循環也就成了實實在在的CPU殺手,可以佔去大量的CPU時間(取決於操作系統)。其實解決很簡單,對readBytes進行判斷,如果爲-1則跳出循環。
這個例子告訴我們:對循環一定要搞清循環的循環規模、每次循環體執行時間、循環結束條件包括異常情況等,只有這樣才能寫出高效且沒有隱患的代碼。
相關文章
-
J2EE系統優化之對象與循環簡介
優化一般意義上說是提高已有系統的性能,減少如內存、數據庫、網絡帶寬等資源的佔用,是在系統開發告一段落的前提下進行。yjbys小編分享一篇J2EE系統優化之對象與循環給大家,希望大家認真閱讀!條例一:儘量重用對象,避免創建 -
J2EE架構環境監控系統設計
下面是小編整理的從環境監控實際出發設計採用了基於J2EE開發平臺、B/S模式的環境監控系統設計方案。並進行了系統的數據結構設計、三層結構的系統設計以及系統功能設計的文章。 一、系統主要模塊本系統的功能爲能 -
SUN認證考試知識點:OSCache提升J2EE系統運行性能
Cache是一種用於提高系統響應速度、改善系統運行性能的技術。尤其是在Web應用中,通過緩存頁面的輸出結果,可以很顯着的改善系統運行性能。本文中作者給大家介紹一個實現J2EE框架中Web應用層緩存功能的開放源代碼項目--- -
關於J2EE系統異常的處理準則
J2EE核心是一組技術規範與指南,其中所包含的各類組件、服務架構及技術層次,均有共同的標準及規格,讓各種依循J2EE架構的不同平臺之間,存在良好的兼容性。下面是小編整理的關於J2EE系統異常的處理準則,歡迎大家參考! J2E -
J2EE工程師知識點:JPA的優勢
J2EE規範是這樣定義J2EE組件的:客戶端應用程序和applet是運行在客戶端的組件;Java Servlet和Java Server Pages (JSP) 是運行在服務器端的Web組件;Enterprise Java Bean (EJB )組件是運行在服務器端的業務組件。下面Y -
Eclipse j2ee開發環境的搭建
你是一個全面發展的好學生。你文靜溫和,大家都願意和你一起玩。上課時你能積極思考老師提出的問題。每次作業也完成得很好,令老師感到非常滿意。每次的值日工作你都能出色地完成。如果你能一如既往的走下去,將會是老師、 -
win10系統下安裝Java SE與環境變量
導讀:本文以win10系統和當前最新的Java SE Development Kit 8 爲例給大家做講解,win7、win8系統教程也大同小異,但不建議在winxp下安裝配置JDK8。就跟隨本站小編一起去了解下吧,想了解更多相關信息請持續關注我們應屆畢業 -
婦產科主治醫師知識點:循環系統的變化
1.心臟心臟向左、向上、向前移位,心濁界稍擴大。心臟容量從妊娠早期至妊娠末期約增加10%,心率每分鐘增加10~15次。心尖部聞及柔和吹風樣收縮期雜音。 2.心搏量心搏量自妊娠10周增加,妊娠32~34周達高峯。 3.血壓 -
j2ee培訓:如何構建RESTful Web Service
JavaEE的核心是EJB3.0, 其提供了更兼便捷的企業級的應用框架。下面yjbys小編爲大家準備了關於如何構建RESTful Web Service的.文章,歡迎閱讀。 1. 首先是實體類,注意其中的@XmlRootElement註解package s;import ;imp -
j2ee和JSP的關係
J2EE是Java 2 Enterprise Eidtion,它們是Sun公司建立在Java語言上的一種服務器端的編程技術,簡單來說,它是用來動態生成網頁的一種技術,現在的主要對手是微軟主推的。 JSP和J2EE的關係簡述JSP應該是屬於J2EE的一部分,JS