JAVA性能優化-通用篇

 「通用篇」討論的問題適合於大多數Java應用。java

  1.1 不用new關鍵詞建立類的實例設計模式

  用new關鍵詞建立類的實例時,構造函數鏈中的全部構造函數都會被自動調用。但若是一個對象實現了Cloneable接口,咱們能夠調用它的clone()方法。clone()方法不會調用任何類構造函數。數組

  在使用設計模式(Design Pattern)的場合,若是用Factory模式建立對象,則改用clone()方法建立新的對象實例很是簡單。例如,下面是Factory模式的一個典型實現:服務器

public static Credit getNewCredit() 
{併發

   return new Credit();ide

  }函數

 


改進後的代碼使用clone()方法,以下所示:性能

private static Credit BaseCredit = new Credit(); 
public static Credit getNewCredit()優化

  {spa

   return (Credit) BaseCredit.clone();

  }


上面的思路對於數組處理一樣頗有用。


1.2 使用非阻塞I/O

  版本較低的JDK不支持非阻塞I/O API。爲避免I/O阻塞,一些應用採用了建立大量線程的辦法(在較好的狀況下,會使用一個緩衝池)。這種技術能夠在許多必須支持併發I/O流的應用中見到,如Web服務器、報價和拍賣應用等。然而,建立Java線程須要至關可觀的開銷。

  JDK 1.4引入了非阻塞的I/O庫(java.nio)。若是應用要求使用版本較早的JDK,在這裏有一個支持非阻塞I/O的軟件包。

  1.3 慎用異常

  異常對性能不利。拋出異常首先要建立一個新的對象。Throwable接口的構造函數調用名爲fillInStackTrace()的本地 (Native)方法,fillInStackTrace()方法檢查堆棧,收集調用跟蹤信息。只要有異常被拋出,VM就必須調整調用堆棧,由於在處理過程當中建立了一個新的對象。

  異常只能用於錯誤處理,不該該用來控制程序流程。

  1.4 不要重複初始化變量

  默認狀況下,調用類的構造函數時, Java會把變量初始化成肯定的值:全部的對象被設置成null,整數變量(byte、short、int、long)設置成0,float和 double變量設置成0.0,邏輯值設置成false。當一個類從另外一個類派生時,這一點尤爲應該注意,由於用new關鍵詞建立一個對象時,構造函數鏈中的全部構造函數都會被自動調用。

  1.5 儘可能指定類的final修飾符

  帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String。爲String類指定final防止了人們覆蓋length()方法。

  另外,若是指定一個類爲final,則該類全部的方法都是final。Java編譯器會尋找機會內聯(inline)全部的final方法(這和具體的編譯器實現有關)。此舉可以使性能平均提升50%。

  1.6 儘可能使用局部變量

  調用方法時傳遞的參數以及在調用中建立的臨時變量都保存在棧(Stack)中,速度較快。其餘變量,如靜態變量、實例變量等,都在堆(Heap)中建立,速度較慢。另外,依賴於具體的編譯器/JVM,局部變量還可能獲得進一步優化。請參見《儘量使用堆棧變量》。

  1.7 乘法和除法

  考慮下面的代碼:

  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。值得一提的是,雖然移位操做速度快,但可能使代碼比較難於理解,因此最好加上一些註釋。

相關文章
相關標籤/搜索