影響JAVA代碼運行效率 java提高代碼執(zhí)行效率

對于java語言來說,大量注釋會影響執(zhí)行效率么

Java代碼注釋寫的多,會影響到編譯效率,但是不會影響到執(zhí)行效率。

伊金霍洛網站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網頁設計、網站建設、微信開發(fā)、APP開發(fā)、自適應網站建設等網站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)建站從2013年成立到現(xiàn)在10年的時間,我們擁有了豐富的建站經驗和運維經驗,來保證我們的工作的順利進行。專注于網站建設就選創(chuàng)新互聯(lián)建站。

Java代碼是先編譯成字節(jié)碼,然后被JVM解釋執(zhí)行的。

我做了個實驗

TimeDemo 類

import?java.util.ArrayList;

public?class?TimeDemo?{

public?static?void?main(String[]?args)?{

long?start?=?System.currentTimeMillis();

ArrayListInteger?list?=?new?ArrayListInteger();

for?(int?i?=?0;?i?1000000;?i++)?{

list.add(i);

}

long?end?=?System.currentTimeMillis();

System.out.println("本次執(zhí)行耗費了"+(end-start)+"毫秒");

}

}

TimeDemo2

import?java.util.ArrayList;

public?class?TimeDemo2?{

public?static?void?main(String[]?args)?{

long?start?=?System.currentTimeMillis();

ArrayListInteger?list?=?new?ArrayListInteger();

for?(int?i?=?0;?i?1000000;?i++)?{

list.add(i);

}

//用java.io生成了很多行的注釋,

//注釋

//注釋

//注釋

//注釋

//注釋

long?end?=?System.currentTimeMillis();

System.out.println("本次執(zhí)行耗費了"+(end-start)+"毫秒");

}

}

運行結果

當注釋行數是1~1萬行的時候. 能較快的編譯

當注釋行數達到1百萬的時候,編譯稍微慢一點

當注釋行數達到1千萬行的時候, CPU占用100%,卡了進1分鐘也沒有編譯完成,只好強行關閉

結論:

簡單明了的注釋有助于程序猿對代碼的讀寫

只有當注釋行數極大的時候,才會嚴重的影響編譯速度。 但不會影響執(zhí)行速度

對于java語言來說,大量注釋會影響執(zhí)行效率么?

肯定會影響執(zhí)行效率的啊。你在大量注釋的時候需要的各種字符都是需要時間和精力的,在你花大把精力過多注釋的時候,你的時間就浪費到里面了,這樣整體的執(zhí)行力肯定會受影響的。

Java代碼的優(yōu)化方法有哪些

說到代碼優(yōu)化,每個人或多或少都掌握一到兩種方法,但是這樣的方法對提升代碼運行效率效果不大,最重要是對代碼的重視和了解,這樣才能提升代碼的運行效率。在進行代碼優(yōu)化的過程中,方法是非常重要的,多掌握幾種方法,根據代碼的不同情況選擇適合的方法進行優(yōu)化。下面電腦培訓為大家介紹Java代碼優(yōu)化的幾種方法。

1、使用指定類、方法的final修飾符

具有final修飾符的類不可派生。在Java核心API中,有許多最終應用程序的例子,例如java.lang.String,整個類都是final。為類指定final修飾符允許繼承類,并且為方法指定final修飾符允許覆蓋該方法。如果將類指定為final,IT培訓認為該類的所有方法都是final。Java編譯器將尋找內聯(lián)所有最終方法的機會。內聯(lián)對于提高Java操作的效率非常重要。這可以將性能平均提高50%。

2、重用對象

String對象的使用是非常重要的,StringBuilder/StringBuffer并不是字符串連接。由于Java虛擬機需要時間來生成對象,所以將來垃圾收集和處理這些對象可能需要一些時間。因此,生成太多對象將對程序的性能產生很大影響。

3、使用局部變量

調用方法時傳遞的參數以及在調用中創(chuàng)建的臨時變量都保存在堆棧中,速度更快。其他變量(如靜態(tài)變量和實例變量)在堆中創(chuàng)建并且速度較慢。此外,昆明北大青鳥發(fā)現(xiàn)在堆棧中創(chuàng)建的變量,當方法完成運行時,內容消失,不需要進行額外的垃圾收集。

4、及時關閉流

在Java編程過程中,在執(zhí)行數據庫連接和I/O流操作時要小心。使用后,北大青鳥云南嘉薈校區(qū)官網建議應及時關閉以釋放資源。因為這些大型物體的操作會導致系統(tǒng)的大量開銷,稍微粗心會導致嚴重的后果。

如何優(yōu)化JAVA代碼及提高執(zhí)行效率

可供程序利用的資源(內存、CPU時間、網絡帶寬等)是有限的,優(yōu)化的目的就是讓程序用盡可能少的資源完成預定的任務。優(yōu)化通常包含兩方面的內容:減小代碼的體積,提高代碼的運行效率。本文討論的主要是如何提高代碼的效率。

在Java程序中,性能問題的大部分原因并不在于Java語言,而是在于程序本身。養(yǎng)成好的代碼編寫習慣非常重要,比如正確地、巧妙地運用java.lang.String類和java.util.Vector類,它能夠顯著地提高程序的性能。下面我們就來具體地分析一下這方面的問題。

1、 盡量指定類的final修飾符帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String。為String類指定final防止了人們覆蓋length()方法。另外,如果指定一個類為final,則該類所有的方法都是final。Java編譯器會尋找機會內聯(lián)(inline)所有的final方法(這和具體的編譯器實現(xiàn)有關)。此舉能夠使性能平均提高50%

。

2、 盡量重用對象。特別是String 對象的使用中,出現(xiàn)字符串連接情況時應用StringBuffer 代替。由于系統(tǒng)不僅要花時間生成對象,以后可能還需花時間對這些對象進行垃圾回收和處理。因此,生成過多的對象將會給程序的性能帶來很大的影響。

3、 盡量使用局部變量,調用方法時傳遞的參數以及在調用中創(chuàng)建的臨時變量都保存在棧(Stack)中,速度較快。其他變量,如靜態(tài)變量、實例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。另外,依賴于具體的編譯器/JVM,局部變量還可能得到進一步優(yōu)化。請參見《盡可能使用堆棧變量》。

4、 不要重復初始化變量 默認情況下,調用類的構造函數時,

Java會把變量初始化成確定的值:所有的對象被設置成null,整數變量(byte、short、int、long)設置成0,float和double變量設置成0.0,邏輯值設置成false。當一個類從另一個類派生時,這一點尤其應該注意,因為用new關鍵詞創(chuàng)建一個對象時,構造函數鏈中的所有構造函數都會被自動調用。

5、 在JAVA + ORACLE 的應用系統(tǒng)開發(fā)中,java中內嵌的SQL語句盡量使用大寫的形式,以減輕ORACLE解析器的解析負擔。

6、 Java 編程過程中,進行數據庫連接、I/O流操作時務必小心,在使用完畢后,即使關閉以釋放資源。因為對這些大對象的操作會造成系統(tǒng)大的開銷,稍有不慎,會導致嚴重的后果。

7、 由于JVM的有其自身的GC機制,不需要程序開發(fā)者的過多考慮,從一定程度上減輕了開發(fā)者負擔,但同時也遺漏了隱患,過分的創(chuàng)建對象會消耗系統(tǒng)的大量內存,嚴重時會導致內存泄露,因此,保證過期對象的及時回收具有重要意義。JVM回收垃圾的條件是:對象不在被引用;然而,JVM的GC并非十分的機智,即使對象滿足了垃圾回收的條件也不一定會被立即回收。所以,建議我們在對象使用完畢,應手動置成null。

8、 在使用同步機制時,應盡量使用方法同步代替代碼塊同步。

9、 盡量減少對變量的重復計算

例如:for(int i = 0;i list.size; i ++) {

}

應替換為:

for(int i = 0,int len = list.size();i len; i ++) {

}

10、盡量采用lazy loading 的策略,即在需要的時候才開始創(chuàng)建。

例如: String str = “aaa”;

if(i == 1) {

list.add(str);

}

應替換為:

if(i == 1) {

String str = “aaa”;

list.add(str);

}

11、慎用異常

異常對性能不利。拋出異常首先要創(chuàng)建一個新的對象。Throwable接口的構造函數調用名為fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法檢查堆棧,收集調用跟蹤信息。只要有異常被拋出,VM就必須調整調用堆棧,因為在處理過程中創(chuàng)建了一個新的對象。異常只能用于錯誤處理,不應該用來控制程序流程。

12、不要在循環(huán)中使用:

Try {

} catch() {

}

應把其放置在最外層。

13、StringBuffer 的使用:

StringBuffer表示了可變的、可寫的字符串。

有三個構造方法 :

StringBuffer (); //默認分配16個字符的空間

StringBuffer (int size); //分配size個字符的空間

StringBuffer (String str); //分配16個字符+str.length()個字符空間

你可以通過StringBuffer的構造函數來設定它的初始化容量,這樣可以明顯地提升性能。這里提到的構造函數是StringBuffer(int

length),length參數表示當前的StringBuffer能保持的字符數量。你也可以使用ensureCapacity(int

minimumcapacity)方法在StringBuffer對象創(chuàng)建之后設置它的容量。首先我們看看StringBuffer的缺省行為,然后再找出一條更好的提升性能的途徑。

StringBuffer在內部維護一個字符數組,當你使用缺省的構造函數來創(chuàng)建StringBuffer對象的時候,因為沒有設置初始化字符長度,StringBuffer的容量被初始化為16個字符,也就是說缺省容量就是16個字符。當StringBuffer達到最大容量的時候,它會將自身容量增加到當前的2倍再加2,也就是(2*舊值+2)。如果你使用缺省值,初始化之后接著往里面追加字符,在你追加到第16個字符的時候它會將容量增加到34(2*16+2),當追加到34個字符的時候就會將容量增加到70(2*34+2)。無論何事只要StringBuffer到達它的最大容量它就不得不創(chuàng)建一個新的字符數組然后重新將舊字符和新字符都拷貝一遍――這也太昂貴了點。所以總是給StringBuffer設置一個合理的初始化容量值是錯不了的,這樣會帶來立竿見影的性能增益。

StringBuffer初始化過程的調整的作用由此可見一斑。所以,使用一個合適的容量值來初始化StringBuffer永遠都是一個最佳的建議。

14、合理的使用Java類 java.util.Vector。

簡單地說,一個Vector就是一個java.lang.Object實例的數組。Vector與數組相似,它的元素可以通過整數形式的索引訪問。但是,Vector類型的對象在創(chuàng)建之后,對象的大小能夠根據元素的增加或者刪除而擴展、縮小。請考慮下面這個向Vector加入元素的例子:

Object obj = new Object();

Vector v = new Vector(100000);

for(int I=0;

I100000; I++) { v.add(0,obj); }

除非有絕對充足的理由要求每次都把新元素插入到Vector的前面,否則上面的代碼對性能不利。在默認構造函數中,Vector的初始存儲能力是10個元素,如果新元素加入時存儲能力不足,則以后存儲能力每次加倍。Vector類就象StringBuffer類一樣,每次擴展存儲能力時,所有現(xiàn)有的元素都要復制到新的存儲空間之中。下面的代碼片段要比前面的例子快幾個數量級:

Object obj = new Object();

Vector v = new Vector(100000);

for(int I=0; I100000; I++) { v.add(obj); }

同樣的規(guī)則也適用于Vector類的remove()方法。由于Vector中各個元素之間不能含有“空隙”,刪除除最后一個元素之外的任意其他元素都導致被刪除元素之后的元素向前移動。也就是說,從Vector刪除最后一個元素要比刪除第一個元素“開銷”低好幾倍。

假設要從前面的Vector刪除所有元素,我們可以使用這種代碼:

for(int I=0; I100000; I++)

{

 v.remove(0);

}

但是,與下面的代碼相比,前面的代碼要慢幾個數量級:

for(int I=0; I100000; I++)

{

 v.remove(v.size()-1);

}

從Vector類型的對象v刪除所有元素的最好方法是:

v.removeAllElements();

假設Vector類型的對象v包含字符串“Hello”??紤]下面的代碼,它要從這個Vector中刪除“Hello”字符串:

String s = "Hello";

int i = v.indexOf(s);

if(I != -1) v.remove(s);

這些代碼看起來沒什么錯誤,但它同樣對性能不利。在這段代碼中,indexOf()方法對v進行順序搜索尋找字符串“Hello”,remove(s)方法也要進行同樣的順序搜索。改進之后的版本是:

String s = "Hello";

int i = v.indexOf(s);

if(I != -1) v.remove(i);

這個版本中我們直接在remove()方法中給出待刪除元素的精確索引位置,從而避免了第二次搜索。一個更好的版本是:

String s = "Hello"; v.remove(s);

最后,我們再來看一個有關Vector類的代碼片段:

for(int I=0; I++;I v.length)

如果v包含100,000個元素,這個代碼片段將調用v.size()方法100,000次。雖然size方法是一個簡單的方法,但它仍舊需要一次方法調用的開銷,至少JVM需要為它配置以及清除堆棧環(huán)境。在這里,for循環(huán)內部的代碼不會以任何方式修改Vector類型對象v的大小,因此上面的代碼最好改寫成下面這種形式:

int size = v.size(); for(int I=0; I++;Isize)

雖然這是一個簡單的改動,但它仍舊贏得了性能。畢竟,每一個CPU周期都是寶貴的。

15、當復制大量數據時,使用System.arraycopy()命令。

16、代碼重構:增強代碼的可讀性。

例如:

public class ShopCart {

private List carts ;

public void add (Object item) {

if(carts == null) {

carts = new ArrayList();

}

crts.add(item);

}

public void remove(Object item) {

if(carts. contains(item)) {

carts.remove(item);

}

}

public List getCarts() {

//返回只讀列表

return Collections.unmodifiableList(carts);

}

//不推薦這種方式

//this.getCarts().add(item);

}

17、不用new關鍵詞創(chuàng)建類的實例

用new關鍵詞創(chuàng)建類的實例時,構造函數鏈中的所有構造函數都會被自動調用。但如果一個對象實現(xiàn)了Cloneable接口,我們可以調用它的clone()方法。clone()方法不會調用任何類構造函數。

在使用設計模式(Design Pattern)的場合,如果用Factory模式創(chuàng)建對象,則改用clone()方法創(chuàng)建新的對象實例非常簡單。例如,下面是Factory模式的一個典型實現(xiàn):

public static Credit getNewCredit() {

return new Credit();

}

改進后的代碼使用clone()方法,如下所示:

private static Credit BaseCredit = new Credit();

public static Credit getNewCredit() {

return (Credit) BaseCredit.clone();

}

上面的思路對于數組處理同樣很有用。

18、乘法和除法

考慮下面的代碼:

for (val = 0; val 100000; val +=5) {

alterX = val * 8; myResult = val * 2;

}

用移位操作替代乘法操作可以極大地提高性能。下面是修改后的代碼:

for (val = 0; val 100000; val += 5) {

alterX = val 3; myResult = val 1;

}

修改后的代碼不再做乘以8的操作,而是改用等價的左移3位操作,每左移1位相當于乘以2。相應地,右移1位操作相當于除以2。值得一提的是,雖然移位操作速度快,但可能使代碼比較難于理解,所以最好加上一些注釋。

19、在JSP頁面中關閉無用的會話。

一個常見的誤解是以為session在有客戶端訪問時就被創(chuàng)建,然而事實是直到某server端程序調用HttpServletRequest.getSession(true)這樣的語句時才被創(chuàng)建,注意如果JSP沒有顯示的使用 %@pagesession="false"% 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句HttpSession

session = HttpServletRequest.getSession(true);這也是JSP中隱含的session對象的來歷。由于session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。

對于那些無需跟蹤會話狀態(tài)的頁面,關閉自動創(chuàng)建的會話可以節(jié)省一些資源。使用如下page指令:%@ page session="false"%

20、JDBC與I/O

如果應用程序需要訪問一個規(guī)模很大的數據集,則應當考慮使用塊提取方式。默認情況下,JDBC每次提取32行數據。舉例來說,假設我們要遍歷一個5000行的記錄集,JDBC必須調用數據庫157次才能提取到全部數據。如果把塊大小改成512,則調用數據庫的次數將減少到10次。

[p][/p]21、Servlet與內存使用

許多開發(fā)者隨意地把大量信息保存到用戶會話之中。一些時候,保存在會話中的對象沒有及時地被垃圾回收機制回收。從性能上看,典型的癥狀是用戶感到系統(tǒng)周期性地變慢,卻又不能把原因歸于任何一個具體的組件。如果監(jiān)視JVM的堆空間,它的表現(xiàn)是內存占用不正常地大起大落。

解決這類內存問題主要有二種辦法。第一種辦法是,在所有作用范圍為會話的Bean中實現(xiàn)HttpSessionBindingListener接口。這樣,只要實現(xiàn)valueUnbound()方法,就可以顯式地釋放Bean使用的資源。另外一種辦法就是盡快地把會話作廢。大多數應用服務器都有設置會話作廢間隔時間的選項。另外,也可以用編程的方式調用會話的setMaxInactiveInterval()方法,該方法用來設定在作廢會話之前,Servlet容器允許的客戶請求的最大間隔時間,以秒計。

22、使用緩沖標記

一些應用服務器加入了面向JSP的緩沖標記功能。例如,BEA的WebLogic Server從6.0版本開始支持這個功能,Open

Symphony工程也同樣支持這個功能。JSP緩沖標記既能夠緩沖頁面片斷,也能夠緩沖整個頁面。當JSP頁面執(zhí)行時,如果目標片斷已經在緩沖之中,則生成該片斷的代碼就不用再執(zhí)行。頁面級緩沖捕獲對指定URL的請求,并緩沖整個結果頁面。對于購物籃、目錄以及門戶網站的主頁來說,這個功能極其有用。對于這類應用,頁面級緩沖能夠保存頁面執(zhí)行的結果,供后繼請求使用。

23、選擇合適的引用機制

在典型的JSP應用系統(tǒng)中,頁頭、頁腳部分往往被抽取出來,然后根據需要引入頁頭、頁腳。當前,在JSP頁面中引入外部資源的方法主要有兩種:include指令,以及include動作。

include指令:例如%@ include file="copyright.html"

%。該指令在編譯時引入指定的資源。在編譯之前,帶有include指令的頁面和指定的資源被合并成一個文件。被引用的外部資源在編譯時就確定,比運行時才確定資源更高效。

include動作:例如jsp:include page="copyright.jsp"

/。該動作引入指定頁面執(zhí)行后生成的結果。由于它在運行時完成,因此對輸出結果的控制更加靈活。但時,只有當被引用的內容頻繁地改變時,或者在對主頁面的請求沒有出現(xiàn)之前,被引用的頁面無法確定時,使用include動作才合算。

24、及時清除不再需要的會話

為了清除不再活動的會話,許多應用服務器都有默認的會話超時時間,一般為30分鐘。當應用服務器需要保存更多會話時,如果內存容量不足,操作系統(tǒng)會把部分內存數據轉移到磁盤,應用服務器也可能根據“最近最頻繁使用”(Most

Recently

Used)算法把部分不活躍的會話轉儲到磁盤,甚至可能拋出“內存不足”異常。在大規(guī)模系統(tǒng)中,串行化會話的代價是很昂貴的。當會話不再需要時,應當及時調用HttpSession.invalidate()方法清除會話。HttpSession.invalidate()方法通常可以在應用的退出頁面調用。

25、不要將數組聲明為:public static final 。

26、HashMap的遍歷效率討論

經常遇到對HashMap中的key和value值對的遍歷操作,有如下兩種方法:MapString, String[] paraMap = new HashMapString, String[]();

................//第一個循環(huán)

SetString appFieldDefIds = paraMap.keySet();

for (String appFieldDefId : appFieldDefIds) {

String[] values = paraMap.get(appFieldDefId);

......

}

//第二個循環(huán)

for(EntryString, String[] entry : paraMap.entrySet()){

String appFieldDefId = entry.getKey();

String[] values = entry.getValue();

.......

}

第一種實現(xiàn)明顯的效率不如第二種實現(xiàn)。

分析如下 SetString appFieldDefIds = paraMap.keySet(); 是先從HashMap中取得keySet

代碼如下:

public SetK keySet() {

SetK ks = keySet;

return (ks != null ? ks : (keySet = new KeySet()));

}

private class KeySet extends AbstractSetK {

public IteratorK iterator() {

return newKeyIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsKey(o);

}

public boolean remove(Object o) {

return HashMap.this.removeEntryForKey(o) != null;

}

public void clear() {

HashMap.this.clear();

}

}

其實就是返回一個私有類KeySet, 它是從AbstractSet繼承而來,實現(xiàn)了Set接口。

再來看看for/in循環(huán)的語法

for(declaration : expression_r)

statement

在執(zhí)行階段被翻譯成如下各式

for(IteratorE #i = (expression_r).iterator(); #i.hashNext();){

declaration = #i.next();

statement

}

因此在第一個for語句for (String appFieldDefId : appFieldDefIds) 中調用了HashMap.keySet().iterator() 而這個方法調用了newKeyIterator()

IteratorK newKeyIterator() {

return new KeyIterator();

}

private class KeyIterator extends HashIteratorK {

public K next() {

return nextEntry().getKey();

}

}

所以在for中還是調用了

在第二個循環(huán)for(EntryString, String[] entry : paraMap.entrySet())中使用的Iterator是如下的一個內部類

private class EntryIterator extends HashIteratorMap.EntryK,V {

public Map.EntryK,V next() {

return nextEntry();

}

}

此時第一個循環(huán)得到key,第二個循環(huán)得到HashMap的Entry

效率就是從循環(huán)里面體現(xiàn)出來的第二個循環(huán)此致可以直接取key和value值

而第一個循環(huán)還是得再利用HashMap的get(Object key)來取value值

現(xiàn)在看看HashMap的get(Object key)方法

public V get(Object key) {

Object k = maskNull(key);

int hash = hash(k);

int i = indexFor(hash, table.length); //Entry[] table

EntryK,V e = table;

while (true) {

if (e == null)

return null;

if (e.hash == hash eq(k, e.key))

return e.value;

e = e.next;

}

}

其實就是再次利用Hash值取出相應的Entry做比較得到結果,所以使用第一中循環(huán)相當于兩次進入HashMap的Entry中

而第二個循環(huán)取得Entry的值之后直接取key和value,效率比第一個循環(huán)高。其實按照Map的概念來看也應該是用第二個循環(huán)好一點,它本來就是key和value的值對,將key和value分開操作在這里不是個好選擇。

網頁標題:影響JAVA代碼運行效率 java提高代碼執(zhí)行效率
網頁地址:http://muchs.cn/article24/dohdice.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供外貿建站網站改版、網站維護、關鍵詞優(yōu)化、做網站、網站營銷

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務器托管