版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、 J2EE平臺架構(gòu)性能優(yōu)化方案應(yīng)用J2EE平臺開發(fā)的系統(tǒng)的性能是系統(tǒng)使用者和開發(fā)者都關(guān)注的問題,本文從服務(wù)器端編程時應(yīng)注意的幾個方面討論代碼對性能的影響,并總結(jié)一些解決的建議。關(guān)鍵詞:性能,Java,J2EE,EJB,Servlet,JDBC 一、概要Java 2 Platform, Enterprise Edition (J2EE)是當(dāng)前很多商業(yè)應(yīng)用系統(tǒng)使用的開發(fā)平臺,該技術(shù)提供了一個基于組件的方法來設(shè)計、開發(fā)、裝配和部署企業(yè)級應(yīng)用程序。J2EE平臺提供了一個多層結(jié)構(gòu)的分布式的應(yīng)用程序模型,可以更快地開發(fā)和發(fā)布的新的應(yīng)用解決方案。J2EE是一種技術(shù)規(guī)范,定義了整個標(biāo)準(zhǔn)的應(yīng)用開發(fā)體系結(jié)構(gòu)和一個
2、部署環(huán)境,應(yīng)用開發(fā)者開發(fā)時只要專注于具體商業(yè)邏輯和商業(yè)業(yè)務(wù)規(guī)則的實現(xiàn)上,而其他的諸如事務(wù)、持久化、安全等系統(tǒng)開發(fā)問題可以由應(yīng)用程序容器或者服務(wù)器處理,開發(fā)完成后,就可以方便地部署到實現(xiàn)規(guī)范的應(yīng)用服務(wù)器中。作為網(wǎng)絡(luò)上的商業(yè)應(yīng)用系統(tǒng),同時訪問的人數(shù)是很多的,在大量訪問的情況下,過多的資源請求和有限的服務(wù)器資源(內(nèi)存、CPU時間、網(wǎng)絡(luò)帶寬等)之間就會出現(xiàn)矛盾,應(yīng)用系統(tǒng)的性能就顯得很重要了,有時正確的代碼并不能保證項目的成功,性能往往是最后決定一個項目是否成功關(guān)鍵。本文主要從性能的角度出發(fā),討論J2EE服務(wù)器端的代碼性能優(yōu)化和提升。二、常見的Java 編程 J2EE語言基礎(chǔ)是Java,常用的Java代
3、碼問題對應(yīng)用系統(tǒng)的性能影響,下面討論了一些應(yīng)該注意方面。使用StringBuffer代替String 當(dāng)處理字符串的相加時,常見的寫法是:String str1 = Hello;String str2 = welcome to world;String str3 = str1 + , + str2 +!;System.out.println(str3);很多人都知道,這樣的代碼效率是很低的,因為String是用來存儲字符串常量的,如果要執(zhí)行“”的操作,系統(tǒng)會生成一些臨時的對象,并對這些對象進(jìn)行管理,造成不必要的開銷。如果字符串有連接的操作,替代的做法是用StringBuffer類的append
4、方法,它的缺省構(gòu)造函數(shù)和append的實現(xiàn)是:public StringBuffer() / 構(gòu)造函數(shù)this(16); / 缺省容量16 public synchronized StringBuffer append(String str) if (str = null) str = String.valueOf(str); int len =str.length(); int newcount = count + len; if(newcount value.length) expandCapacity(newcount); / 擴(kuò)充容量str.getChars(0, len, value
5、, count); count = newcount; return this; 當(dāng)字符串的大小超過缺省16時,代碼實現(xiàn)了容量的擴(kuò)充,為了避免對象的重新擴(kuò)展其容量,更好的寫法為:StringBuffer buffer = new StringBuffer(30); / 分配指定的大小。buffer.append(hello); buffer.append(,); buffer.append(welcometo world!); String str = buffer.toString();生成對象時,分配合理的空間和大小Java中的很多類都有它的默認(rèn)的空間分配大小,對于一些有大小的對象的初始化
6、,應(yīng)該預(yù)計對象的大小,然后使用進(jìn)行初始化,上面的例子也說明了這個問題,StringBuffer創(chuàng)建時,我們指定了它的大小。另外的一個例子是Vector,當(dāng)聲明Vector vectnew Vector()時,系統(tǒng)調(diào)用:public Vector() / 缺省構(gòu)造函數(shù)this(10); / 容量是 10;缺省分配10個對象大小容量。當(dāng)執(zhí)行add方法時,可以看到具體實現(xiàn)為:. public synchronized boolean add(Object o) modCount+;ensureCapacityHelper(elementCount+1);elementDataelementCount
7、+ =o;return true;private void ensureCapacityHelper(int minCapacity) int oldCapacity = elementData.length; if (minCapacity oldCapacity) Object oldData = elementData; int newCapacity = (capacityIncrement 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2); if (newCapacity minCapacity) newCapaci
8、ty = minCapacity; elementData = new ObjectnewCapacity; System.arraycopy(oldData, 0, elementData, 0, elementCount); 我們可以看到,當(dāng)Vector大小超過原來的大小時,一些代碼的目的就是為了做容量的擴(kuò)充,在預(yù)先知道該Vector大小的話,可以指定其大小,避免容量擴(kuò)充的開銷,如知道Vector大小為100時,初始化是就可以象這樣。Vector vect . new Vector(100);優(yōu)化循環(huán)體循環(huán)是比較重復(fù)運行的地方,如果循環(huán)次數(shù)很大,循環(huán)體內(nèi)不好的代碼對效率的影響就會被放大而變
9、的突出??紤]下面的代碼片:. Vector vect = new Vector(1000);.for( inti=0; isize; i+).如果size=1000,就可以減少1000次size()的系統(tǒng)調(diào)用開銷,避免了循環(huán)體重復(fù)調(diào)用。再看如下的代碼片:. for (int i = 0;i ;i+)if (i%10 = 9) . / 每十次執(zhí)行一次改寫成也可以提高效率:. for(inti =0,j =10; i0 )value =object.getValue();可以修改為:int value;if(i0 )NewObject object = new NewObject(); Value
10、 =object.getValue(); 另外,應(yīng)該盡量重復(fù)使用一個對象,而不是聲明新的同類對象。一個重用對象的方法是改變對象的值,如可以通過setValue之類的方法改變對象的變量達(dá)到重用的目的。變量的注意事項盡量使用局部變量,調(diào)用方法時傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時變量都保存在棧(Stack) 中,速度較快。其他變量,如靜態(tài)變量、實例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。盡量使用靜態(tài)變量,即加修飾符static,如果類中的變量不會隨他的實例而變化,就可以定義為靜態(tài)變量,從而使他所有的實例都共享這個變量。方法(Method)調(diào)用在Java中,一切都是對象,如果有方法(Method)調(diào)
11、用,處理器先要檢查該方法是屬于哪個對象,該對象是否有效,對象屬于什么類型,然后選擇合適的方法并調(diào)用??梢詼p少方法的調(diào)用,同樣一個方法: public void CallMethod(int i )if( i =0 )return;. / 其他處理如果直接調(diào)用,int i = 0; . CallMethod(i);就不如寫成:int i = 0; . if( i =0 ) CallMethod(i); 不影響可讀性等情況下,可以把幾個小的方法合成一個大的方法。另外,在方法前加上final,private關(guān)鍵字有利于編譯器的優(yōu)化。慎用異常處理 異常是Java的一種錯誤處理機(jī)制,對程序來說是非常有用
12、的,但是異常對性能不利。拋出異常首先要創(chuàng)建一個新的對象,并進(jìn)行相關(guān)的處理,造成系統(tǒng)的開銷,所以異常應(yīng)該用在錯誤處理的情況,不應(yīng)該用來控制程序流程,流程盡量用while,if等處理。在不是很影響代碼健壯性的前提下,可以把幾個try/catch塊合成一個。同步同步主要出現(xiàn)在多線程的情況,為多線程同時運行時提供對象數(shù)據(jù)安全的機(jī)制,多線程是比較復(fù)雜話題,應(yīng)用多線程也是為了獲得性能的提升,應(yīng)該盡可能減少同步。另外,如果需要同步的地方,可以減少同步的代碼段,如只同步某個方法或函數(shù),而不是整個代碼。使用Java系統(tǒng)APIJava的API一般都做了性能的考慮,如果完成相同的功能,優(yōu)先使用API而不是自己寫的代
13、碼,如數(shù)組復(fù)制通常的代碼如下: int size = 1000;String strArray1 = new Stringsize;String strArray2 = new Stringsize;for(inti=0;isize;i+) / 賦值strArray1i = (new String(Array: + i);for(inti=0;isize;i+) / 復(fù)制strArray2i=(new String(String)ai);如果使用Java提供的API,就可以提高性能:int size = 1000;String strArray1 = new Stringsize;String
14、 strArray2 = new Stringsize;for(inti=0;isize;i+) / 賦值strArray1i = (new String(Array: + i);System.arraycopy(strArray1,0,strArray2,0,size); / 復(fù)制同樣的一個規(guī)則是,當(dāng)有大量數(shù)據(jù)的復(fù)制時,應(yīng)該使用System.arraycopy()。 三、I/O 性能輸入/輸出(I/O)包括很多方面,我們知道,進(jìn)行I/O操作是很費系統(tǒng)資源的。程序中應(yīng)該盡量少用I/O操作。使用時可以注意: . 合理控制輸出函數(shù)System.out.println()對于大多時候是有用的,特別是
15、系統(tǒng)調(diào)試的時候,但也會產(chǎn)生大量的信息出現(xiàn)在控制臺和日志上,同時輸出時,有序列化和同步的過程,造成了開銷。特別是在發(fā)行版中,要合理的控制輸出,可以在項目開發(fā)時,設(shè)計好一個Debug的工具類,在該類中可以實現(xiàn)輸出開關(guān),輸出的級別,根據(jù)不同的情況進(jìn)行不同的輸出的控制。使用緩存讀寫內(nèi)存要比讀寫文件要快很多,應(yīng)盡可能使用緩沖。盡可能使用帶有Buffer的類代替沒有Buffer的類,如可以用BufferedReader 代替Reader,用BufferedWriter代替Writer來進(jìn)行處理I/O操作。同樣可以用BufferedInputStream代替InputStream都可以獲得性能的提高。四、S
16、ervletServlet采用請求響應(yīng)模式提供Web服務(wù),通過ServletResponse以及ServletRequest這兩個對象來輸出和接收用戶傳遞的參數(shù),在服務(wù)器端處理用戶的請求,根據(jù)請求訪問數(shù)據(jù)庫、訪問別的Servlet方法、調(diào)用EJB等等,然后將處理結(jié)果返回給客戶端。盡量不使用同步Servlet是多線程的,以處理不同的請求,基于前面同步的分析,如果有太多的同步就失去了多線程的優(yōu)勢了。 不用保存太多的信息在HttpSession中很多時候,存儲一些對象在HttpSession中是有必要的,可以加快系統(tǒng)的開發(fā),如網(wǎng)上商店系統(tǒng)會把購物車信息保存在該用戶的Session中,但當(dāng)存儲大量的信
17、息或是大的對象在會話中是有害的,特別是當(dāng)系統(tǒng)中用戶的訪問量很大,對內(nèi)存的需求就會很高。具體開發(fā)時,在這兩者之間應(yīng)作好權(quán)衡。清除Session通常情況,當(dāng)達(dá)到設(shè)定的超時時間時,同時有些Session沒有了活動,服務(wù)器會釋放這些沒有活動的Session,. 不過這種情況下,特別是多用戶并訪時,系統(tǒng)內(nèi)存要維護(hù)多個的無效Session。當(dāng)用戶退出時,應(yīng)該手動釋放,回收資源,實現(xiàn)如下:. HttpSession theSession = request.getSession(); / 獲取當(dāng)前Sessionif(theSession != null) theSession.invalidate(); /
18、 使該Session失效五、EJB 問題EJB是Java服務(wù)器端服務(wù)框架的規(guī)范,軟件廠商根據(jù)它來實現(xiàn)EJB服務(wù)器。應(yīng)用程序開發(fā)者可以專注于支持應(yīng)用所需的商業(yè)邏輯,而不用擔(dān)心周圍框架的實現(xiàn)問題。EJB規(guī)范詳細(xì)地解釋了一些最小但是必須的服務(wù),如事務(wù),安全和名字等。緩存Home接口EJB庫使用Enterprise Bean 的客戶端通過它的Home接口創(chuàng)建它的實例??蛻舳四芡ㄟ^JNDI訪問它。服務(wù)器通過Lookup方法來獲取。JNDI是個遠(yuǎn)程對象,通過RMI方式調(diào)用,對它的訪問往往是比較費時的。所以,在設(shè)計時可以設(shè)計一個類專門用來緩存Home接口,在系統(tǒng)初始化時就獲得需要的Home接口并緩存,以后的
19、引用只要引用緩存即可。封裝Entity Bean直接訪問Entity Bean是個不好的習(xí)慣,用會話Bean封裝對實體Bean的訪問能夠改進(jìn)事務(wù)管理,因為每一個對get方法的直接調(diào)用將產(chǎn)生一個事務(wù),容器將在每一個實體Bean的事務(wù)之后執(zhí)行一個“Load-Store”. 操作。最好在Session Bean中完成Entity Bean的封裝,減少容器的事務(wù)處理,并在Session Bean中實現(xiàn)一些具體的業(yè)務(wù)方法。釋放有狀態(tài)的Session Bean相當(dāng)于HttpSession,當(dāng)把一個Session Bean設(shè)為Stateful,即有狀態(tài)的Session Bean 后,應(yīng)用容器(Contain
20、er)就可能有“鈍化”(Passivate)和活化(Activate)過程,即在主存和二級緩存之間對SessionBean進(jìn)行存儲位置的轉(zhuǎn)移,在這個過程中,存在序列化過程。通常有狀態(tài)Session Bean的釋放是在超時時發(fā)生,容器自動的清除該對象,但是如果交給容器管理,一方面可能產(chǎn)生對象鈍化,另一方面未超時期間,系統(tǒng)還要 維護(hù)一份該對象,所以如果我們確認(rèn)使用完該StatefulSession Bean后不再需要時,可以顯式的將其釋放掉,方法是調(diào)用:theSesionBean.remove();六、數(shù)據(jù)庫訪問在J2EE開發(fā)的應(yīng)用系統(tǒng)中,數(shù)據(jù)庫訪問一般是個必備的環(huán)節(jié)。數(shù)據(jù)庫用來存儲業(yè)務(wù)數(shù)據(jù),供應(yīng)
21、用程序訪問。在Java技術(shù)的應(yīng)用體系中,應(yīng)用程序是通過JDBC(Java Database Connectivity)實現(xiàn)的接口來訪問數(shù)據(jù)庫的,JDBC支持“建立連接、SQL語句查詢、處理結(jié)果”等基本功能。在應(yīng)用JDBC接口訪問數(shù)據(jù)庫的過程中,只要根據(jù)規(guī)范來實現(xiàn),就可以達(dá)到要求的功能。但是,有些時候進(jìn)行數(shù)據(jù)查詢的效率著實讓開發(fā)人員不如所愿,明明根據(jù)規(guī)范編寫的程序,運行效果卻很差,造成整個系統(tǒng)的執(zhí)行效率不高。使用速度快的JDBC驅(qū)動JDBC API包括兩種實現(xiàn)接口形式,一種是純Java實現(xiàn)的驅(qū)動,一種利用ODBC驅(qū)動和數(shù)據(jù)庫客戶端實現(xiàn),具體有四種驅(qū)動模式并各有不同的應(yīng)用范圍,針對不同的應(yīng)用開發(fā)要
22、選擇合適的JDBC驅(qū)動,在同一個應(yīng)用系統(tǒng)中,如果選擇不同的JDBC驅(qū)動,在效率上會有差別。例如,有一個企業(yè)應(yīng)用系統(tǒng),不要求支持不同廠商的數(shù)據(jù)庫,這時就可以選擇模式4的JDBC驅(qū)動,該驅(qū)動一般由數(shù)據(jù)庫廠商實現(xiàn)的基于本地協(xié)議的驅(qū)動,直接調(diào)用數(shù)據(jù)庫管理系統(tǒng)使用的協(xié)議,減少了模式3中的中間層。使用JDBC連接池為了提高訪問數(shù)據(jù)庫的性能,我們還可以使用JDBC 2.0的一些規(guī)范和特性,JDBC是占用資源的,在使用數(shù)據(jù)庫連接時可以使用連接池Connection Pooling,避免頻繁打開、關(guān)閉Connection。而我們知道,獲取Connection是比較消耗系統(tǒng)資源的。Connection緩沖池是這樣
23、工作的:當(dāng)一個應(yīng)用程序關(guān)閉一個數(shù)據(jù)庫連接時,這個連接并不真正釋放而是被循環(huán)利用,建立連接是消耗較大的操作,循環(huán)利用連接可以顯著的提高性能,因為可以減少新連接的建立。一個通過DataSource獲取緩沖池獲得連接,并連接到一個CustomerDB數(shù)據(jù)源的代碼演示如下:Context ctx = new InitialContext();DataSource dataSource = (DataSource) ctx.lookup(jdbc/CustomerDB);Connection conn = dataSource.getConnection(password,username);緩存Dat
24、aSource一個DataSource對象代表一個實際的數(shù)據(jù)源。這個數(shù)據(jù)源可以是從關(guān)系數(shù)據(jù)庫到表格形式的文件,完全依賴于它是怎樣實現(xiàn)的,一個數(shù)據(jù)源對象注冊到JNDI名字服務(wù)后,應(yīng)用程序就可以從JNDI服務(wù)器上取得該對象,并使用之和數(shù)據(jù)源建立連接。通過上面的例子,我們知道DataSource是從連接池獲得連接的一種方式,通過JNDI方式獲得,是占用資源的。為了避免再次的JNDI調(diào)用,可以系統(tǒng)中緩存要使用的DataSource。關(guān)閉所有使用的資源系統(tǒng)一般是并發(fā)的系統(tǒng),在每次申請和使用完資源后,應(yīng)該釋放供別人使用,數(shù)據(jù)庫資源每個模式的含義可以參考SUN JDBC的文檔,不同是比較寶貴的,使用完成后應(yīng)
25、該保證徹底的釋放。 請看下面的代碼段: Connection conn = null; Statement stmt = null; ResultSet rs = null; try DataSource dataSource = getDataSource(); / 取的DataSource的方法,實現(xiàn)略。conn = datasource.getConnection(); stmt = conn.createStatement(); rs = stmt.executeQuery(SELECT * FROM .); . / 其他處理rs.close();stmt.close();conn.c
26、lose();catch (SQLException ex) . / 錯誤處理粗看似乎沒有什么問題,也有關(guān)閉相關(guān)如Connection等系統(tǒng)資源的代碼,但當(dāng)出現(xiàn)異常后,關(guān)閉資源的代碼可能并不被執(zhí)行,為保證資源的確實已被關(guān)閉,應(yīng)該把資源關(guān)閉的代碼放到finally塊:Connection conn = null; Statement stmt = null; ResultSet rs = null; try DataSource dataSource = getDataSource(); / 取的DataSource的方法,實現(xiàn)略。conn = datasource.getConnection(); stmt = conn.createStatement(); rs = st
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中西醫(yī)結(jié)合護(hù)理學(xué)基礎(chǔ)
- 企業(yè)績效考核制度
- 2026年電動側(cè)滑門控制器項目商業(yè)計劃書
- 醫(yī)學(xué)影像學(xué)在腫瘤預(yù)防中的應(yīng)用
- 醫(yī)療人才培養(yǎng)體系優(yōu)化
- 醫(yī)院內(nèi)部培訓(xùn)效果評估方法優(yōu)化
- 醫(yī)療機(jī)構(gòu)人力資源管理與效能
- 《GB-T 22576.2-2021醫(yī)學(xué)實驗室 質(zhì)量和能力的要求 第2部分:臨床血液學(xué)檢驗領(lǐng)域的要求》專題研究報告
- 《GBT 3758-2008卡套式管接頭用錐密封焊接接管》專題研究報告
- 《FZT 53007-2017導(dǎo)電錦綸6毛條》專題研究報告
- 2025年廣東省深圳市中考英語復(fù)習(xí)聽說題型課件信息復(fù)述提問
- 咖啡消費人群的細(xì)分與定位-全面剖析
- 09.品質(zhì)月報統(tǒng)計表模板
- 游戲推廣合作協(xié)議書范本
- 2024-2025學(xué)年北京朝陽區(qū)九年級初三(上)期末歷史試卷(含答案)
- 2025版國家開放大學(xué)法學(xué)本科《知識產(chǎn)權(quán)法》期末紙質(zhì)考試總題庫
- DB11T 354-2023 生活垃圾收集運輸管理規(guī)范
- 赤石特大橋施工安全風(fēng)險評估報告
- QBT 2770-2006 羽毛球拍行業(yè)標(biāo)準(zhǔn)
- 售后服務(wù)流程管理手冊
- 2020-2021學(xué)年新概念英語第二冊-Lesson14-同步習(xí)題(含答案)
評論
0/150
提交評論