版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、.1. 底層篇1.1. 基本數(shù)據(jù)類(lèi)型時(shí)間分析int的運(yùn)算速度最快,short次之,byte再次之,long再次之。float和double運(yùn)算速度最慢。除法比乘法慢的太多,基本上除法是乘法的9倍時(shí)間。當(dāng)然,除了浮點(diǎn)型外。根據(jù)intel cpu的參考數(shù)據(jù),乘法計(jì)算時(shí)間是移位運(yùn)算的4-5倍是比較正常的。long類(lèi)型的計(jì)算很慢,建議一般少使用它。double運(yùn)算速度和float相當(dāng);浮點(diǎn)的乘法比除法要慢。但是,這個(gè)結(jié)果并不能真正說(shuō)明問(wèn)題。這個(gè)結(jié)果只是一個(gè)一般性的,在特殊情況下,乘法還是比除法快,比如:floata * floatb 仍然是比f(wàn)loata / (1/floatb)快。從實(shí)際的數(shù)據(jù)結(jié)果來(lái)
2、講,乘法的時(shí)候,乘數(shù)越小速度越快,特別是在乘數(shù)比3小的時(shí)候,乘法時(shí)耗接近20,大于4的時(shí)候,幾乎都是600的時(shí)耗。除法恰好相反,除數(shù)大于1的時(shí)候,時(shí)耗一般都是350,可是,當(dāng)除數(shù)小于1的時(shí)候,時(shí)耗就變成了700了。對(duì)于大家關(guān)心的移位和乘除2的問(wèn)題,jdk5.0已經(jīng)做了部分處理。即“var *=2”和“var =1”耗費(fèi)一樣。但是,除法并沒(méi)有進(jìn)行這類(lèi)處理,即“var /= 2”耗費(fèi)和基本的除法一樣。1.2. 類(lèi)和接口調(diào)用時(shí)間分析1.2.1. 類(lèi)的創(chuàng)建 雖然面向?qū)ο笏枷胍呀?jīng)深入人心,但他在帶來(lái)快捷方面的編程風(fēng)格的時(shí)候,也帶來(lái)了低下的效率。在java中,反應(yīng)最快的是object類(lèi)(這也是顯然的),建
3、立一個(gè)新的object類(lèi)時(shí)耗僅僅為20單位。而一個(gè)空類(lèi)(即沒(méi)有聲明任何methods和fields)的建立時(shí)間則增加到了驚人的400單位。如果再給類(lèi)增加一些字段的話(huà),時(shí)間耗費(fèi)并沒(méi)有特別大的增加,每增加一個(gè)int類(lèi)型字段大概增加30個(gè)單位。僅僅就創(chuàng)建時(shí)間來(lái)說(shuō),內(nèi)嵌的類(lèi)型都有不錯(cuò)的表現(xiàn)。比如,創(chuàng)建一個(gè)int數(shù)組(僅僅包含一個(gè)元素)的時(shí)間只比創(chuàng)建一個(gè)object對(duì)象的時(shí)間多一倍。當(dāng)然,如果你創(chuàng)建的數(shù)組對(duì)象包含1000個(gè)元素的話(huà),其創(chuàng)建時(shí)間顯然還會(huì)加上內(nèi)存管理的時(shí)間了,它的時(shí)間大概是1萬(wàn)個(gè)時(shí)間單位。請(qǐng)注意,我們這里討論的時(shí)間單位其實(shí)十分小,1萬(wàn)個(gè)時(shí)間單位也僅僅只是有0.006毫秒(0.000006秒)
4、。創(chuàng)建一個(gè)byte、short、int、long、float和double數(shù)組對(duì)象的時(shí)間消耗幾乎是一樣的。1.2.2. 方法的調(diào)用java在這個(gè)方面有一點(diǎn)做得很好,就是調(diào)用一個(gè)只有很少量代碼的方法的時(shí)耗和直接把這段代碼寫(xiě)到本地的時(shí)耗相差很小。當(dāng)然不包括需要分配很多本地變量的情況。調(diào)用本類(lèi)(this指針)的方法是最快的,時(shí)間在1-2個(gè)單位。調(diào)用其它類(lèi)的靜態(tài)方法也很快,速度和調(diào)用本來(lái)方法差不多。調(diào)用其它類(lèi)的非靜態(tài)方法速度就慢一些,在1.5-2.5個(gè)時(shí)間單位之間。調(diào)用繼承接口的方法是十分緩慢的,是調(diào)用普通方法的3倍。但是,如果在實(shí)現(xiàn)接口的時(shí)候加上final關(guān)鍵字的話(huà),調(diào)用這個(gè)方法的時(shí)耗就和普通方法差
5、不多了。最慢的是已經(jīng)同步化了的方法。即加上了synchronized關(guān)鍵字的方法。調(diào)用它的時(shí)耗比普通方法高出了近20倍。如果不是萬(wàn)不得已,不要把synchronized加到方法上面,實(shí)在不行的話(huà),你可以把它加到代碼塊上去,這種加法比直接加到方法上面快一點(diǎn)。注意,因?yàn)榉椒ù蟛糠謺r(shí)候都是完成很多事情的,所以,十分注意調(diào)用方法的開(kāi)銷(xiāo)是沒(méi)有必要的,因?yàn)檫@個(gè)時(shí)間和方法執(zhí)行需要的時(shí)間比較起來(lái)只是毛毛雨。1.3. 基本操作時(shí)間耗費(fèi)2. 通用篇“通用篇”討論的問(wèn)題適合于大多數(shù)java應(yīng)用。2.1. 不用new關(guān)鍵詞創(chuàng)建類(lèi)的實(shí)例用new關(guān)鍵詞創(chuàng)建類(lèi)的實(shí)例時(shí),構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會(huì)被自動(dòng)調(diào)用。但如果一個(gè)對(duì)
6、象實(shí)現(xiàn)了cloneable接口,我們可以調(diào)用它的clone()方法。clone()方法不會(huì)調(diào)用任何類(lèi)構(gòu)造函數(shù)。在使用設(shè)計(jì)模式(design pattern)的場(chǎng)合,如果用factory模式創(chuàng)建對(duì)象,則改用clone()方法創(chuàng)建新的對(duì)象實(shí)例非常簡(jiǎn)單。例如,下面是factory模式的一個(gè)典型實(shí)現(xiàn):public static credit getnewcredit() return new credit();改進(jìn)后的代碼使用clone()方法,如下所示:private static credit basecredit = new credit();public static credit getne
7、wcredit() return (credit) basecredit.clone();上面的思路對(duì)于數(shù)組處理同樣很有用。2.2. 使用非阻塞i/o版本較低的jdk不支持非阻塞i/o api。為避免i/o阻塞,一些應(yīng)用采用了創(chuàng)建大量線(xiàn)程的辦法(在較好的情況下,會(huì)使用一個(gè)緩沖池)。這種技術(shù)可以在許多必須支持并發(fā)i/o流的應(yīng)用中見(jiàn)到,如web服務(wù)器、報(bào)價(jià)和拍賣(mài)應(yīng)用等。然而,創(chuàng)建java線(xiàn)程需要相當(dāng)可觀(guān)的開(kāi)銷(xiāo)。jdk 1.4引入了非阻塞的i/o庫(kù)(java.nio)。如果應(yīng)用要求使用版本較早的jdk,在這里有一個(gè)支持非阻塞i/o的軟件包。請(qǐng)參見(jiàn)sun中國(guó)網(wǎng)站的調(diào)整java的i/o性能。2.3. 慎
8、用異常異常對(duì)性能不利。拋出異常首先要?jiǎng)?chuàng)建一個(gè)新的對(duì)象。throwable接口的構(gòu)造函數(shù)調(diào)用名為fillinstacktrace()的本地(native)方法,fillinstacktrace()方法檢查堆棧,收集調(diào)用跟蹤信息。只要有異常被拋出,vm就必須調(diào)整調(diào)用堆棧,因?yàn)樵谔幚磉^(guò)程中創(chuàng)建了一個(gè)新的對(duì)象。異常只能用于錯(cuò)誤處理,不應(yīng)該用來(lái)控制程序流程。2.4. 不要重復(fù)初始化變量默認(rèn)情況下,調(diào)用類(lèi)的構(gòu)造函數(shù)時(shí), java會(huì)把變量初始化成確定的值:所有的對(duì)象被設(shè)置成null,整數(shù)變量(byte、short、int、long)設(shè)置成0,float和 double變量設(shè)置成0.0,邏輯值設(shè)置成false
9、。當(dāng)一個(gè)類(lèi)從另一個(gè)類(lèi)派生時(shí),這一點(diǎn)尤其應(yīng)該注意,因?yàn)橛胣ew關(guān)鍵詞創(chuàng)建一個(gè)對(duì)象時(shí),構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會(huì)被自動(dòng)調(diào)用。2.5. 盡量使用局部變量調(diào)用方法時(shí)傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時(shí)變量都保存在棧(stack)中,速度較快。其他變量,如靜態(tài)變量、實(shí)例變量等,都在堆(heap)中創(chuàng)建,速度較慢。另外,依賴(lài)于具體的編譯器/jvm,局部變量還可能得到進(jìn)一步優(yōu)化。請(qǐng)參見(jiàn)盡可能使用堆棧變量。2.6. 位移完成乘法和除法考慮下面的代碼:for (val = 0; val 100000; val +=5) alterx = val * 8; myresult = val * 2; 用移位操作替代乘
10、法操作可以極大地提高性能。下面是修改后的代碼:for (val = 0; val 100000; val += 5) alterx = val 3; myresult = val 1; 修改后的代碼不再做乘以8的操作,而是改用等價(jià)的左移3位操作,每左移1位相當(dāng)于乘以2。相應(yīng)地,右移1位操作相當(dāng)于除以2。值得一提的是,雖然移位操作速度快,但可能使代碼比較難于理解,所以最好加上一些注釋。2.7. 避免在循環(huán)體中創(chuàng)建對(duì)象,即使該對(duì)象占用內(nèi)存空間不大.for(int i=0;i10000;+i) object obj = new object(); system.out.println(obj=+ob
11、j); 應(yīng)改成object obj = null; for(int i=0;i10000;+i) obj = new object(); system.out.println(obj=+obj); 2.8. 當(dāng)做數(shù)組拷貝操作時(shí),采用system.arraycopy()方法2.9. 盡量避免在循環(huán)體中調(diào)用方法2.10. 盡量避免在循環(huán)體中使用try-catch 塊2.11. 在多重循環(huán)中,如果有可能,盡量將最長(zhǎng)的循環(huán)放在最內(nèi)層,最短的循環(huán)放在最外層,以減少循環(huán)層間的變換次數(shù)2.12. 如果預(yù)知長(zhǎng)度,就設(shè)置arraylist的長(zhǎng)度2.13. 避免在類(lèi)在構(gòu)造器的初始化其他類(lèi)2.14. 盡量避免在構(gòu)造
12、中對(duì)靜態(tài)變量做賦值操作2.15. 不要在類(lèi)的構(gòu)造器中創(chuàng)建類(lèi)的實(shí)例3. jsp/servlet篇3.1. 采用out 對(duì)象中的print方法代替println()方法3.2. 采用適當(dāng)?shù)闹党跏蓟痮ut 對(duì)象緩沖區(qū)的大小3.3. 盡量采用forward()方法重定向新的jsp3.4. 通過(guò)init()方法來(lái)緩存一些靜態(tài)數(shù)據(jù)以提高應(yīng)用性能.3.5. servletoutputstream 取代 printwriter4. db篇4.1. 純jdbc最快4.2. 最重要的是盡量減少與數(shù)據(jù)庫(kù)通信的次數(shù),多使用批處理4.3. 設(shè)置合適的fetch_size和batch_size4.4. 采用連接池技術(shù)4.
13、5. 選擇合適的事務(wù)隔離層與及時(shí)關(guān)閉連接對(duì)象4.6. preparedstatement防止sql注入4.7. 盡可能地做批處理更新5. 內(nèi)存篇5.1. 別用new boolean()在很多場(chǎng)景中boolean類(lèi)型是必須的,比如jdbc中boolean類(lèi)型的set與get都是通過(guò)boolean封裝傳遞的,大部分orm也是用boolean來(lái)封裝boolean類(lèi)型的,比如:ps.setboolean(isclosed,new boolean(true);ps.setboolean(isclosed,new boolean(isclosed);ps.setboolean(isclosed,new b
14、oolean(i=3);通常這些系統(tǒng)中構(gòu)造的boolean實(shí)例的個(gè)數(shù)是相當(dāng)多的,所以系統(tǒng)中充滿(mǎn)了大量boolean實(shí)例小對(duì)象,這是相當(dāng)消耗內(nèi)存的。boolean類(lèi)實(shí)際上只要兩個(gè)實(shí)例就夠了,一個(gè)true的實(shí)例,一個(gè)false的實(shí)例。boolean類(lèi)提供兩了個(gè)靜態(tài)變量:public static final boolean true = new boolean(true);public static final boolean false = new boolean(false);需要的時(shí)候只要取這兩個(gè)變量就可以了,比如:ps.setboolean(isclosed,boolean.true);那
15、么象2、3句那樣要根據(jù)一個(gè)boolean變量來(lái)創(chuàng)建一個(gè)boolean怎么辦呢?可以使用boolean提供的靜態(tài)方法: boolean.valueof()比如:ps.setboolean(isclosed,boolean.valueof(isclosed);ps.setboolean(isclosed,boolean.valueof(i=3);因?yàn)関alueof的內(nèi)部實(shí)現(xiàn)是:return (b ? true : false);所以可以節(jié)省大量?jī)?nèi)存。相信如果java規(guī)范直接把boolean的構(gòu)造函數(shù)規(guī)定成private,就再也不會(huì)出現(xiàn)這種情況了。5.2. 別用new integer 和boolea
16、n類(lèi)似,java開(kāi)發(fā)中使用integer封裝int的場(chǎng)合也非常多,并且通常用int表示的數(shù)值通常都非常小。sun sdk中對(duì)integer的實(shí)例化進(jìn)行了優(yōu)化,integer類(lèi)緩存了-128到127這256個(gè)狀態(tài)的integer,如果使用integer.valueof(int i),傳入的int范圍正好在此內(nèi),就返回靜態(tài)實(shí)例。這樣如果我們使用integer.valueof代替new integer的話(huà)也將大大降低內(nèi)存的占用。如果您的系統(tǒng)要在不同的sdk(比如ibm sdk)中使用的話(huà),那么可以自己做了工具類(lèi)封裝一下,比如integerutils.valueof(),這樣就可以在任何sdk中都可以
17、使用這種特性。5.3. 用stringbuffer代替字符串相加這個(gè)我就不多講了,因?yàn)橐呀?jīng)被人講過(guò)n次了。我只想將一個(gè)不是笑話(huà)的笑話(huà),我在看國(guó)內(nèi)某“著名”java開(kāi)發(fā)的web系統(tǒng)的源碼中,竟然發(fā)現(xiàn)其中大量的使用字符串相加,一個(gè)拼裝sql語(yǔ)句的方法中竟然最多構(gòu)造了將近100個(gè)string實(shí)例。無(wú)語(yǔ)中!5.4. 過(guò)濫使用哈希表有一定開(kāi)發(fā)經(jīng)驗(yàn)的開(kāi)發(fā)人員經(jīng)常會(huì)使用hash表(hash表在jdk中的一個(gè)實(shí)現(xiàn)就是hashmap)來(lái)緩存一些數(shù)據(jù),從而提高系統(tǒng)的運(yùn)行速度。比如使用hashmap緩存一些物料信息、人員信息等基礎(chǔ)資料,這在提高系統(tǒng)速度的同時(shí)也加大了系統(tǒng)的內(nèi)存占用,特別是當(dāng)緩存的資料比較多的時(shí)候。其
18、實(shí)我們可以使用操作系統(tǒng)中的緩存的概念來(lái)解決這個(gè)問(wèn)題,也就是給被緩存的分配一個(gè)一定大小的緩存容器,按照一定的算法淘汰不需要繼續(xù)緩存的對(duì)象,這樣一方面會(huì)因?yàn)檫M(jìn)行了對(duì)象緩存而提高了系統(tǒng)的運(yùn)行效率,同時(shí)由于緩存容器不是無(wú)限制擴(kuò)大,從而也減少了系統(tǒng)的內(nèi)存占用?,F(xiàn)在有很多開(kāi)源的緩存實(shí)現(xiàn)項(xiàng)目,比如ehcache、oscache等,這些項(xiàng)目都實(shí)現(xiàn)了fifo、mru等常見(jiàn)的緩存算法。5.5. 避免過(guò)深的類(lèi)層次結(jié)構(gòu)和過(guò)深的方法調(diào)用因?yàn)檫@兩者都是非常占用內(nèi)存的(特別是方法調(diào)用更是堆??臻g的消耗大戶(hù))。5.6. 變量只有在用到它的時(shí)候才定義和實(shí)例化5.7. 盡量避免使用static變量,類(lèi)內(nèi)私有常量可以用final來(lái)
19、代替6. jvm篇6.1. 內(nèi)存管理java的內(nèi)存管理就是對(duì)象的分配和釋放問(wèn)題。在java中,程序員需要通過(guò)關(guān)鍵字new為每個(gè)對(duì)象申請(qǐng)內(nèi)存空間 (基本類(lèi)型除外),所有的對(duì)象都在堆 (heap)中分配空間。對(duì)象的釋放是由gc決定和執(zhí)行的。在java中,內(nèi)存的分配是由程序完成的,而內(nèi)存的釋放是由gc完成的,這種收支兩條線(xiàn)的方法簡(jiǎn)化了程序員的工作。但也加重了jvm的工作。這也是java程序運(yùn)行速度較慢的原因之一。6.1.1. gc釋放空間方法監(jiān)控每一個(gè)對(duì)象的運(yùn)行狀態(tài),包括對(duì)象的申請(qǐng)、引用、被引用、賦值等。當(dāng)該對(duì)象不再被引用時(shí),釋放對(duì)象。6.1.2. 內(nèi)存管理結(jié)構(gòu)java使用有向圖的方式進(jìn)行內(nèi)存管理,
20、對(duì)于程序的每一個(gè)時(shí)刻,我們都有一個(gè)有向圖表示jvm的內(nèi)存分配情況。將對(duì)象考慮為有向圖的頂點(diǎn),將引用關(guān)系考慮為圖的有向邊,有向邊從引用者指向被引對(duì)象。另外,每個(gè)線(xiàn)程對(duì)象可以作為一個(gè)圖的起始頂點(diǎn),例如大多程序從main進(jìn)程開(kāi)始執(zhí)行,那么該圖就是以main進(jìn)程頂點(diǎn)開(kāi)始的一棵根樹(shù)。在這個(gè)有向圖中,根頂點(diǎn)可達(dá)的對(duì)象都是有效對(duì)象,gc將不回收這些對(duì)象。如果某個(gè)對(duì)象 (連通子圖)與這個(gè)根頂點(diǎn)不可達(dá)(注意,該圖為有向圖),那么我們認(rèn)為這個(gè)(這些)對(duì)象不再被引用,可以被gc回收。使用有向圖方式管理內(nèi)存的優(yōu)缺點(diǎn)java使用有向圖的方式進(jìn)行內(nèi)存管理,可以消除引用循環(huán)的問(wèn)題,例如有三個(gè)對(duì)象,相互引用,只要它們和根進(jìn)程
21、不可達(dá)的,那么gc也是可以回收它們的。這種方式的優(yōu)點(diǎn)是管理內(nèi)存的精度很高,但是效率較低。另外一種常用的內(nèi)存管理技術(shù)是使用計(jì)數(shù)器,例如com模型采用計(jì)數(shù)器方式管理構(gòu)件,它與有向圖相比,精度行低(很難處理循環(huán)引用的問(wèn)題),但執(zhí)行效率很高。6.1.3. java的內(nèi)存泄露java雖然由gc來(lái)回收內(nèi)存,但也是存在泄露問(wèn)題的,只是比c+小一點(diǎn)。c+所有對(duì)象的分配和回收都需要由用戶(hù)來(lái)管理。即需要管理點(diǎn),也需要管理邊。若存在不可達(dá)的點(diǎn),無(wú)法回收分配給那個(gè)點(diǎn)的內(nèi)存,導(dǎo)致內(nèi)存泄露。存在無(wú)用的對(duì)象引用,自然也會(huì)導(dǎo)致內(nèi)存泄露。java由gc來(lái)管理內(nèi)存回收,gc將回收不可達(dá)的對(duì)象占用的內(nèi)存空間。所以,java需要考慮的內(nèi)存泄露問(wèn)題主要是那些被引用但無(wú)用的對(duì)象即指要管理
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 鐵路工程模板施工合同
- 橄欖球俱樂(lè)部急救藥箱使用規(guī)范
- 救援設(shè)備租賃合同
- 汽車(chē)報(bào)廢處理流程
- 高爾夫球場(chǎng)租賃經(jīng)營(yíng)合同
- 教育機(jī)構(gòu)服務(wù)質(zhì)量控制
- 教師勞動(dòng)合同范本科研項(xiàng)目
- 果園管理服務(wù)租賃協(xié)議
- 信息技術(shù)公司員工班車(chē)使用指南
- 設(shè)計(jì)住房屋租賃合同范本
- 初中語(yǔ)文人教八年級(jí)上冊(cè)《誠(chéng)信綜合實(shí)踐》PPT
- 奧齒泰-工具盒使用精講講解學(xué)習(xí)課件
- DB32T 4353-2022 房屋建筑和市政基礎(chǔ)設(shè)施工程檔案資料管理規(guī)程
- 航空小鎮(zhèn)主題樂(lè)園項(xiàng)目規(guī)劃設(shè)計(jì)方案
- 保潔冬季防滑防凍工作措施
- 少兒美術(shù)課件-《我的情緒小怪獸》
- 拆除工程原始記錄
- 重視圍透析期慢性腎臟病患者的管理課件
- 預(yù)應(yīng)力鋼絞線(xiàn)張拉伸長(zhǎng)量計(jì)算程序單端(自動(dòng)版)
- 企業(yè)內(nèi)部審計(jì)情況報(bào)表
- 基坑監(jiān)測(cè)課件ppt版(共155頁(yè))
評(píng)論
0/150
提交評(píng)論