本文目錄一覽:
- 1、如何優化JAVA程序開發,提高JAVA性能
- 2、如何提高Java性能
- 3、如何編寫高度優化的Java程序
- 4、Java性能如何優化?
- 5、java中大量數據如何提高性能?
- 6、怎麼做JAVA程序性能優化
如何優化JAVA程序開發,提高JAVA性能
可供程序利用的資源(內存、CPU時間、網絡帶寬等)是有限的,優化的目的就是讓程序用儘可能少的資源完成預定的任務。優化通常包含兩方面的內容:減小代碼的體積,提高代碼的運行效率。本文討論的主要是如何提高代碼的效率。
在Java程序中,性能問題的大部分原因並不在於Java語言,而是在於程序本身。養成好的代碼編寫習慣非常重要,比如正確地、巧妙地運用java.lang.String類和java.util.Vector類,它能夠顯著地提高程序的性能。下面我們就來具體地分析一下這方面的問題。
1、 盡量指定類的final修飾符帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String。為String類指定final防止了人們覆蓋length()方法。另外,如果指定一個類為final,則該類所有的方法都是final。Java編譯器會尋找機會內聯(inline)所有的final方法(這和具體的編譯器實現有關)。此舉能夠使性能平均提高50%
。
2、 盡量重用對象。特別是String 對象的使用中,出現字符串連接情況時應用StringBuffer 代替。由於系統不僅要花時間生成對象,以後可能還需花時間對這些對象進行垃圾回收和處理。因此,生成過多的對象將會給程序的性能帶來很大的影響。
3、 盡量使用局部變量,調用方法時傳遞的參數以及在調用中創建的臨時變量都保存在棧(Stack)中,速度較快。其他變量,如靜態變量、實例變量等,都在堆(Heap)中創建,速度較慢。另外,依賴於具體的編譯器/JVM,局部變量還可能得到進一步優化。請參見《儘可能使用堆棧變量》。
4、 不要重複初始化變量 默認情況下,調用類的構造函數時,
Java會把變量初始化成確定的值:所有的對象被設置成null,整數變量(byte、short、int、long)設置成0,float和double變量設置成0.0,邏輯值設置成false。當一個類從另一個類派生時,這一點尤其應該注意,因為用new關鍵詞創建一個對象時,構造函數鏈中的所有構造函數都會被自動調用。
5、 在JAVA + ORACLE 的應用系統開發中,java中內嵌的SQL語句盡量使用大寫的形式,以減輕ORACLE解析器的解析負擔。
6、 Java 編程過程中,進行數據庫連接、I/O流操作時務必小心,在使用完畢後,即使關閉以釋放資源。因為對這些大對象的操作會造成系統大的開銷,稍有不慎,會導致嚴重的後果。
7、 由於JVM的有其自身的GC機制,不需要程序開發者的過多考慮,從一定程度上減輕了開發者負擔,但同時也遺漏了隱患,過分的創建對象會消耗系統的大量內存,嚴重時會導致內存泄露,因此,保證過期對象的及時回收具有重要意義。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 的策略,即在需要的時候才開始創建。
例如: String str = “aaa”;
if(i == 1) {
list.add(str);
}
應替換為:
if(i == 1) {
String str = “aaa”;
list.add(str);
}
11、慎用異常
異常對性能不利。拋出異常首先要創建一個新的對象。Throwable接口的構造函數調用名為fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法檢查堆棧,收集調用跟蹤信息。只要有異常被拋出,VM就必須調整調用堆棧,因為在處理過程中創建了一個新的對象。異常只能用於錯誤處理,不應該用來控制程序流程。
12、不要在循環中使用:
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對象創建之後設置它的容量。首先我們看看StringBuffer的缺省行為,然後再找出一條更好的提升性能的途徑。
StringBuffer在內部維護一個字符數組,當你使用缺省的構造函數來創建StringBuffer對象的時候,因為沒有設置初始化字符長度,StringBuffer的容量被初始化為16個字符,也就是說缺省容量就是16個字符。當StringBuffer達到最大容量的時候,它會將自身容量增加到當前的2倍再加2,也就是(2*舊值+2)。如果你使用缺省值,初始化之後接着往裡面追加字符,在你追加到第16個字符的時候它會將容量增加到34(2*16+2),當追加到34個字符的時候就會將容量增加到70(2*34+2)。無論何事只要StringBuffer到達它的最大容量它就不得不創建一個新的字符數組然後重新將舊字符和新字符都拷貝一遍――這也太昂貴了點。所以總是給StringBuffer設置一個合理的初始化容量值是錯不了的,這樣會帶來立竿見影的性能增益。
StringBuffer初始化過程的調整的作用由此可見一斑。所以,使用一個合適的容量值來初始化StringBuffer永遠都是一個最佳的建議。
14、合理的使用Java類 java.util.Vector。
簡單地說,一個Vector就是一個java.lang.Object實例的數組。Vector與數組相似,它的元素可以通過整數形式的索引訪問。但是,Vector類型的對象在創建之後,對象的大小能夠根據元素的增加或者刪除而擴展、縮小。請考慮下面這個向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類一樣,每次擴展存儲能力時,所有現有的元素都要複製到新的存儲空間之中。下面的代碼片段要比前面的例子快幾個數量級:
Object obj = new Object();
Vector v = new Vector(100000);
for(int I=0; I100000; I++) { v.add(obj); }
同樣的規則也適用於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需要為它配置以及清除堆棧環境。在這裡,for循環內部的代碼不會以任何方式修改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關鍵詞創建類的實例
用new關鍵詞創建類的實例時,構造函數鏈中的所有構造函數都會被自動調用。但如果一個對象實現了Cloneable接口,我們可以調用它的clone()方法。clone()方法不會調用任何類構造函數。
在使用設計模式(Design Pattern)的場合,如果用Factory模式創建對象,則改用clone()方法創建新的對象實例非常簡單。例如,下面是Factory模式的一個典型實現:
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在有客戶端訪問時就被創建,然而事實是直到某server端程序調用HttpServletRequest.getSession(true)這樣的語句時才被創建,注意如果JSP沒有顯示的使用 %@pagesession=”false”% 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句HttpSession
session = HttpServletRequest.getSession(true);這也是JSP中隱含的session對象的來歷。由於session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。
對於那些無需跟蹤會話狀態的頁面,關閉自動創建的會話可以節省一些資源。使用如下page指令:%@ page session=”false”%
20、JDBC與I/O
如果應用程序需要訪問一個規模很大的數據集,則應當考慮使用塊提取方式。默認情況下,JDBC每次提取32行數據。舉例來說,假設我們要遍歷一個5000行的記錄集,JDBC必須調用數據庫157次才能提取到全部數據。如果把塊大小改成512,則調用數據庫的次數將減少到10次。
[p][/p]21、Servlet與內存使用
許多開發者隨意地把大量信息保存到用戶會話之中。一些時候,保存在會話中的對象沒有及時地被垃圾回收機制回收。從性能上看,典型的癥狀是用戶感到系統周期性地變慢,卻又不能把原因歸於任何一個具體的組件。如果監視JVM的堆空間,它的表現是內存佔用不正常地大起大落。
解決這類內存問題主要有二種辦法。第一種辦法是,在所有作用範圍為會話的Bean中實現HttpSessionBindingListener接口。這樣,只要實現valueUnbound()方法,就可以顯式地釋放Bean使用的資源。另外一種辦法就是儘快地把會話作廢。大多數應用服務器都有設置會話作廢間隔時間的選項。另外,也可以用編程的方式調用會話的setMaxInactiveInterval()方法,該方法用來設定在作廢會話之前,Servlet容器允許的客戶請求的最大間隔時間,以秒計。
22、使用緩衝標記
一些應用服務器加入了面向JSP的緩衝標記功能。例如,BEA的WebLogic Server從6.0版本開始支持這個功能,Open
Symphony工程也同樣支持這個功能。JSP緩衝標記既能夠緩衝頁面片斷,也能夠緩衝整個頁面。當JSP頁面執行時,如果目標片斷已經在緩衝之中,則生成該片斷的代碼就不用再執行。頁面級緩衝捕獲對指定URL的請求,並緩衝整個結果頁面。對於購物籃、目錄以及門戶網站的主頁來說,這個功能極其有用。對於這類應用,頁面級緩衝能夠保存頁面執行的結果,供後繼請求使用。
23、選擇合適的引用機制
在典型的JSP應用系統中,頁頭、頁腳部分往往被抽取出來,然後根據需要引入頁頭、頁腳。當前,在JSP頁面中引入外部資源的方法主要有兩種:include指令,以及include動作。
include指令:例如%@ include file=”copyright.html”
%。該指令在編譯時引入指定的資源。在編譯之前,帶有include指令的頁面和指定的資源被合併成一個文件。被引用的外部資源在編譯時就確定,比運行時才確定資源更高效。
include動作:例如jsp:include page=”copyright.jsp”
/。該動作引入指定頁面執行後生成的結果。由於它在運行時完成,因此對輸出結果的控制更加靈活。但時,只有當被引用的內容頻繁地改變時,或者在對主頁面的請求沒有出現之前,被引用的頁面無法確定時,使用include動作才合算。
24、及時清除不再需要的會話
為了清除不再活動的會話,許多應用服務器都有默認的會話超時時間,一般為30分鐘。當應用服務器需要保存更多會話時,如果內存容量不足,操作系統會把部分內存數據轉移到磁盤,應用服務器也可能根據“最近最頻繁使用”(Most
Recently
Used)算法把部分不活躍的會話轉儲到磁盤,甚至可能拋出“內存不足”異常。在大規模系統中,串行化會話的代價是很昂貴的。當會話不再需要時,應當及時調用HttpSession.invalidate()方法清除會話。HttpSession.invalidate()方法通常可以在應用的退出頁面調用。
25、不要將數組聲明為:public static final 。
26、HashMap的遍歷效率討論
經常遇到對HashMap中的key和value值對的遍歷操作,有如下兩種方法:MapString, String[] paraMap = new HashMapString, String[]();
…………….//第一個循環
SetString appFieldDefIds = paraMap.keySet();
for (String appFieldDefId : appFieldDefIds) {
String[] values = paraMap.get(appFieldDefId);
……
}
//第二個循環
for(EntryString, String[] entry : paraMap.entrySet()){
String appFieldDefId = entry.getKey();
String[] values = entry.getValue();
…….
}
第一種實現明顯的效率不如第二種實現。
分析如下 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繼承而來,實現了Set接口。
再來看看for/in循環的語法
for(declaration : expression_r)
statement
在執行階段被翻譯成如下各式
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中還是調用了
在第二個循環for(EntryString, String[] entry : paraMap.entrySet())中使用的Iterator是如下的一個內部類
private class EntryIterator extends HashIteratorMap.EntryK,V {
public Map.EntryK,V next() {
return nextEntry();
}
}
此時第一個循環得到key,第二個循環得到HashMap的Entry
效率就是從循環裡面體現出來的第二個循環此致可以直接取key和value值
而第一個循環還是得再利用HashMap的get(Object key)來取value值
現在看看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做比較得到結果,所以使用第一中循環相當於兩次進入HashMap的Entry中
而第二個循環取得Entry的值之後直接取key和value,效率比第一個循環高。其實按照Map的概念來看也應該是用第二個循環好一點,它本來就是key和value的值對,將key和value分開操作在這裡不是個好選擇。
如何提高Java性能
提高JAVA的性能,一般考慮如下的四個主要方面:
(1) 程序設計的方法和模式
一個良好的設計能提高程序的性能,這一點不僅適用於JAVA,也適用也任何的編程語言。因為它充分利用了各種資源,如內存,CPU,高速緩存,對象緩衝池及多線程,從而設計出高性能和可伸縮性強的系統。
當然,為了提高程序的性能而改變原來的設計是比較困難的,但是,程序性能的重要性常常要高於設計上帶來的變化。因此,在編程開始之前就應該有一個好的設計模型和方法。
(2) JAVA布署的環境。
JAVA布署的環境就是指用來解釋和執行JAVA字節碼的技術,一般有如下五種。即解釋指令技術(Interpreter Technology),及時編譯的技術(Just In Time Compilier Technology), 適應性優化技術(Adaptive Optimization Technology), 動態優化,提前編譯為機器碼的技術(Dynamic Optimization,Ahead Of Time Technology)和編譯為機器碼的技術(Translator Technology).
這些技術一般都通過優化線程模型,調整堆和棧的大小來優化JAVA的性能。在考慮提高JAVA的性能時,首先要找到影響JAVA性能的瓶頸(BottleNecks),在確認了設計的合理性後,應該調整JAVA布署的環境,通過改變一些參數來提高JAVA應用程序的性能。具體內容見第二節。
(3) JAVA應用程序的實現
當討論應用程序的性能問題時,大多數的程序員都會考慮程序的代碼,這當然是對的,當更重要的是要找到影響程序性能的瓶頸代碼。為了找到這些瓶頸代碼,我們一般會使用一些輔助的工具,如Jprobe,Optimizit,Vtune以及一些分析的工具如TowerJ Performance等。這些輔助的工具能跟蹤應用程序中執行每個函數或方法所消耗掉的時間,從而改善程序的性能。
(4) 硬件和操作系統
為了提高JAVA應用程序的性能,而採用跟快的CPU和更多的內存,並認為這是提高程序性能的唯一方法,但事實並非如此。實踐經驗和事實證明,只有遭到了應用程序性能的瓶頸,從而採取適當得方法,如設計模式,布署的環境,操作系統的調整,才是最有效的。
3.程序中通常的性能瓶頸。
所有的應用程序都存在性能瓶頸,為了提高應用程序的性能,就要儘可能的減少程序的瓶頸。以下是在JAVA程序中經常存在的性能瓶頸。
了解了這些瓶頸後,就可以有針對性的減少這些瓶頸,從而提高JAVA應用程序的性能
4. 提高JAVA程序性能的步驟
為了提高JAVA程序的性能,需要遵循如下的六個步驟。
a) 明確對性能的具體要求
在實施一個項目之前,必須要明確該項目對於程序性能的具體要求,如:這個應用程序要支持5000個並發的用戶,並且響應時間要在5秒鐘之內。但同時也要明白對於性能的要求不應該同對程序的其他要求衝突。
如何編寫高度優化的Java程序
下面給你提供一些在JAVA程序的設計和編碼中,經常採用的一些方法和技巧,可以提高JAVA程序的性能:
1.對象的生成和大小的調整。
JAVA程序設計中一個普遍的問題就是沒有好好的利用JAVA語言本身提供的函數,從而常常會生成大量的對象(或實例)。由於系統不僅要花時間生成對象,以後可能還需花時間對這些對象進行垃圾回收和處理。因此,生成過多的對象將會給程序的性能帶來很大的影響。
例1:關於String ,StringBuffer,+和append
JAVA語言提供了對於String類型變量的操作。但如果使用不當,會給程序的性能帶來影響。如下面的語句:
String name=new String(“HuangWeiFeng”);
System.out.println(name+”is my name”);
看似已經很精簡了,其實並非如此。為了生成二進制的代碼,要進行如下的步驟和操作:
(1) 生成新的字符串 new String(STR_1);
(2) 複製該字符串;
(3) 加載字符串常量”HuangWeiFeng”(STR_2);
(4) 調用字符串的構架器(Constructor);
(5) 保存該字符串到數組中(從位置0開始);
(6) 從java.io.PrintStream類中得到靜態的out變量;
(7) 生成新的字符串緩衝變量new StringBuffer(STR_BUF_1);
(8) 複製該字符串緩衝變量;
(9) 調用字符串緩衝的構架器(Constructor);
(10) 保存該字符串緩衝到數組中(從位置1開始);
(11) 以STR_1為參數,調用字符串緩衝(StringBuffer)類中的append方法;
(12) 加載字符串常量”is my name”(STR_3);
(13) 以STR_3為參數,調用字符串緩衝(StringBuffer)類中的append方法;
(14) 對於STR_BUF_1執行toString命令;
(15) 調用out變量中的println方法,輸出結果。
由此可以看出,這兩行簡單的代碼,就生成了STR_1,STR_2,STR_3,STR_4和STR_BUF_1五個對象變量。這些生成的類的實例一般都存放在堆中。堆要對所有類的超類,類的實例進行初始化,同時還要調用類極其每個超類的構架器。而這些操作都是非常消耗系統資源的。因此,對對象的生成進行限制,是完全有必要的。
經修改,上面的代碼可以用如下的代碼來替換。
StringBuffer name=new StringBuffer(“HuangWeiFeng”);
System.out.println(name.append(“is my name.”).toString());
系統將進行如下的操作:
(1) 生成新的字符串緩衝變量new StringBuffer(STR_BUF_1);
(2) 複製該字符串緩衝變量;
(3) 加載字符串常量”HuangWeiFeng”(STR_1);
(4) 調用字符串緩衝的構架器(Constructor);
(5) 保存該字符串緩衝到數組中(從位置1開始);
(6) 從java.io.PrintStream類中得到靜態的out變量;
(7) 加載STR_BUF_1;
(8) 加載字符串常量”is my name”(STR_2);
(9) 以STR_2為參數,調用字符串緩衝(StringBuffer)實例中的append方法;
(10) 對於STR_BUF_1執行toString命令(STR_3);
(11)調用out變量中的println方法,輸出結果。
由此可以看出,經過改進後的代碼只生成了四個對象變量:STR_1,STR_2,STR_3和STR_BUF_1.你可能覺得少生成一個對象不會對程序的性能有很大的提高。但下面的代碼段2的執行速度將是代碼段1的2倍。因為代碼段1生成了八個對象,而代碼段2隻生成了四個對象。
代碼段1:
String name= new StringBuffer(“HuangWeiFeng”);
name+=”is my”;
name+=”name”;
代碼段2:
StringBuffer name=new StringBuffer(“HuangWeiFeng”);
name.append(“is my”);
name.append(“name.”).toString();
因此,充分的利用JAVA提供的庫函數來優化程序,對提高JAVA程序的性能時非常重要的.其注意點主要有如下幾方面;
(1) 儘可能的使用靜態變量(Static Class Variables)
如果類中的變量不會隨他的實例而變化,就可以定義為靜態變量,從而使他所有的實例都共享這個變量。
例:
public class foo
{
SomeObject so=new SomeObject();
}
就可以定義為:
public class foo
{
static SomeObject so=new SomeObject();
}
(2) 不要對已生成的對象作過多的改變。
對於一些類(如:String類)來講,寧願在重新生成一個新的對象實例,而不應該修改已經生成的對象實例。
例:
String name=”Huang”;
name=”Wei”;
name=”Feng”;
上述代碼生成了三個String類型的對象實例。而前兩個馬上就需要系統進行垃圾回收處理。如果要對字符串進行連接的操作,性能將得更差,因為系統將不得為此生成更多得臨時變量,如上例1所示。
(3) 生成對象時,要分配給它合理的空間和大小JAVA中的很多類都有它的默認的空間分配大小。對於StringBuffer類來講,默認的分配空間大小是16個字符。如果在程序中使用StringBuffer的空間大小不是16個字符,那麼就必須進行正確的初始化。
(4) 避免生成不太使用或生命周期短的對象或變量。對於這種情況,因該定義一個對象緩衝池。以為管理一個對象緩衝池的開銷要比頻繁的生成和回收對象的開銷小的多。
(5) 只在對象作用範圍內進行初始化。JAVA允許在代碼的任何地方定義和初始化對象。這樣,就可以只在對象作用的範圍內進行初始化。從而節約系統的開銷。
例:
SomeObject so=new SomeObject();
If(x==1) then
{
Foo=so.getXX();
}
可以修改為:
if(x==1) then
{
SomeObject so=new SomeObject();
Foo=so.getXX();
}
2.異常(Exceptions)
JAVA語言中提供了try/catch來發方便用戶捕捉異常,進行異常的處理。但是如果使用不當,也會給JAVA程序的性能帶來影響。因此,要注意以下兩點:
(1) 避免對應用程序的邏輯使用try/catch
如果可以用if,while等邏輯語句來處理,那麼就儘可能的不用try/catch語句。
(2) 重用異常
在必須要進行異常的處理時,要儘可能的重用已經存在的異常對象。以為在異常的處理中,生成一個異常對象要消耗掉大部分的時間。
3. 線程(Threading)
一個高性能的應用程序中一般都會用到線程。因為線程能充分利用系統的資源。在其他線程因為等待硬盤或網絡讀寫而 時,程序能繼續處理和運行。但是對線程運用不當,也會影響程序的性能。
例2:正確使用Vector類
Vector主要用來保存各種類型的對象(包括相同類型和不同類型的對象)。但是在一些情況下使用會給程序帶來性能上的影響。這主要是由Vector類的兩個特點所決定的。第一,Vector提供了線程的安全保護功能。即使Vector類中的許多方法同步。但是如果你已經確認你的應用程序是單線程,這些方法的同步就完全不必要了。第二,在Vector查找存儲的各種對象時,常常要花很多的時間進行類型的匹配。而當這些對象都是同一類型時,這些匹配就完全不必要了。因此,有必要設計一個單線程的,保存特定類型對象的類或集合來替代Vector類.用來替換的程序如下(StringVector.java):
public class StringVector
{
private String [] data;
private int count;
public StringVector()
{
this(10); // default size is 10
}
public StringVector(int initialSize)
{
data = new String[initialSize];
}
public void add(String str)
{
// ignore null strings
if(str == null) { return; }
ensureCapacity(count + 1);
data[count++] = str;
}
private void ensureCapacity(int minCapacity)
{
int oldCapacity = data.length;
if (minCapacity oldCapacity)
{
String oldData[] = data;
int newCapacity = oldCapacity * 2;
data = new String[newCapacity];
System.arraycopy(oldData, 0, data, 0, count);
}
}
public void remove(String str)
{
if(str == null) { return; // ignore null str }
for(int i = 0; i count; i++)
{
// check for a match
if(data[i].equals(str))
{
System.arraycopy(data,i+1,data,i,count-1); // copy data
// allow previously valid array element be gc′d
data[–count] = null;
return;
}
}
}
public final String getStringAt(int index)
{
if(index 0) { return null; }
else if(index count) { return null; // index is # strings }
else { return data[index]; // index is good }
}
}
因此,代碼:
Vector Strings=new Vector();
Strings.add(“One”);
Strings.add(“Two”);
String Second=(String)Strings.elementAt(1);
可以用如下的代碼替換:
StringVector Strings=new StringVector();
Strings.add(“One”);
Strings.add(“Two”);
String Second=Strings.getStringAt(1);
這樣就可以通過優化線程來提高JAVA程序的性能。用於測試的程序如下(TestCollection.java):
import java.util.Vector;
public class TestCollection
{
public static void main(String args [])
{
TestCollection collect = new TestCollection();
if(args.length == 0)
{
System.out.println(“Usage: java TestCollection [ vector | stringvector ]”);
System.exit(1);
}
if(args[0].equals(“vector”))
{
Vector store = new Vector();
long start = System.currentTimeMillis();
for(int i = 0; i 1000000; i++)
{
store.addElement(“string”);
}
long finish = System.currentTimeMillis();
System.out.println((finish-start));
start = System.currentTimeMillis();
for(int i = 0; i 1000000; i++)
{
String result = (String)store.elementAt(i);
}
finish = System.currentTimeMillis();
System.out.println((finish-start));
}
else if(args[0].equals(“stringvector”))
{
StringVector store = new StringVector();
long start = System.currentTimeMillis();
for(int i = 0; i 1000000; i++) { store.add(“string”); }
long finish = System.currentTimeMillis();
System.out.println((finish-start));
start = System.currentTimeMillis();
for(int i = 0; i 1000000; i++) {
String result = store.getStringAt(i);
}
finish = System.currentTimeMillis();
System.out.println((finish-start));
}
}
}
關於線程的操作,要注意如下幾個方面:
(1) 防止過多的同步
如上所示,不必要的同步常常會造成程序性能的下降。因此,如果程序是單線程,則一定不要使用同步。
(2) 同步方法而不要同步整個代碼段
對某個方法或函數進行同步比對整個代碼段進行同步的性能要好。
(3) 對每個對象使用多”鎖”的機制來增大並發。
一般每個對象都只有一個”鎖”,這就表明如果兩個線程執行一個對象的兩個不同的同步方法時,會發生”死鎖”。即使這兩個方法並不共享任何資源。為了避免這個問題,可以對一個對象實行”多鎖”的機制。如下所示:
class foo
{
private static int var1;
private static Object lock1=new Object();
private static int var2;
private static Object lock2=new Object();
public static void increment1()
{
synchronized(lock1)
{
var1++;
}
}
public static void increment2()
{
synchronized(lock2)
{
var2++;
}
}
}
4.輸入和輸出(I/O)
輸入和輸出包括很多方面,但涉及最多的是對硬盤,網絡或數據庫的讀寫操作。對於讀寫操作,又分為有緩存和沒有緩存的;對於數據庫的操作,又可以有多種類型的JDBC驅動器可以選擇。但無論怎樣,都會給程序的性能帶來影響。因此,需要注意如下幾點:
(1) 使用輸入輸出緩衝
儘可能的多使用緩存。但如果要經常對緩存進行刷新(flush),則建議不要使用緩存。
(2) 輸出流(Output Stream)和Unicode字符串
當時用Output Stream和Unicode字符串時,Write類的開銷比較大。因為它要實現Unicode到字節(byte)的轉換.因此,如果可能的話,在使用Write類之前就實現轉換或用OutputStream類代替Writer類來使用。
(3) 當需序列化時使用transient
當序列化一個類或對象時,對於那些原子類型(atomic)或可以重建的原素要表識為transient類型。這樣就不用每一次都進行序列化。如果這些序列化的對象要在網絡上傳輸,這一小小的改變對性能會有很大的提高。
(4) 使用高速緩存(Cache)
對於那些經常要使用而又不大變化的對象或數據,可以把它存儲在高速緩存中。這樣就可以提高訪問的速度。這一點對於從數據庫中返回的結果集尤其重要。
(5) 使用速度快的JDBC驅動器(Driver)
JAVA對訪問數據庫提供了四種方法。這其中有兩種是JDBC驅動器。一種是用JAVA外包的本地驅動器;另一種是完全的JAVA驅動器。具體要使用哪一種得根據JAVA布署的環境和應用程序本身來定。
5.一些其他的經驗和技巧
(1) 使用局部變量。
(2) 避免在同一個類中動過調用函數或方法(get或set)來設置或調用變量。
(3) 避免在循環中生成同一個變量或調用同一個函數(參數變量也一樣)。
(4) 儘可能的使用static,final,private等關鍵字。
(5) 當複製大量數據時,使用System.arraycopy()命令。
Java性能如何優化?
代碼優化細節
1、盡量指定類、方法的final修飾符
帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String,整個類都是final的。為類指定final修飾符可以讓類不可以被繼承,為方法指定final修飾符可以讓方法不可以被重寫。
如果指定了一個類為final,則該類所有的方法都是final的。Java編譯器會尋找機會內聯所有的final方法,內聯對於提升Java運行效率作用重大,具體參見Java運行期優化。此舉能夠使性能平均提高50%。
2、盡量重用對象
特別是String對象的使用,出現字符串連接時應該使用StringBuilder/StringBuffer代替。由於Java虛擬機不僅要花時間生成對象,以後可能還需要花時間對這些對象進行垃圾回收和處理,因此,生成過多的對象將會給程序的性能帶來很大的影響。
3、儘可能使用局部變量
調用方法時傳遞的參數以及在調用中創建的臨時變量都保存在棧中,速度較快,其他變量,如靜態變量、實例變量等,都在堆中創建,速度較慢。另外,棧中創建的變量,隨着方法的運行結束,這些內容就沒了,不需要額外的垃圾回收。
4、及時關閉流
Java編程過程中,進行數據庫連接、I/O流操作時務必小心,在使用完畢後,及時關閉以釋放資源。因為對這些大對象的操作會造成系統大的開銷,稍有不慎,將會導致嚴重的後果。
5、盡量減少對變量的重複計算
明確一個概念,對方法的調用,即使方法中只有一句語句,也是有消耗的,包括創建棧幀、調用方法時保護現場、調用方法完畢時恢復現場等。所以例如下面的操作:
for (int i = 0; i list.size(); i++)
{…}
建議替換為:
for (int i = 0, length = list.size(); i length; i++)
{…}
這樣,在list.size()很大的時候,就減少了很多的消耗
java中大量數據如何提高性能?
通過使用一些輔助性工具來找到程式中的瓶頸,然後就能對瓶頸部分的代碼進行優化。一般有兩種方案:即優化代碼或更改設計方法。我們一般會選擇後者,因為不去調用以下代碼要比調用一些優化的代碼更能提高程式的性能。而一個設計良好的程式能夠精簡代碼,從而提高性能。
????下面將提供一些在JAVA程式的設計和編碼中,為了能夠提高JAVA程式的性能,而經常採用的一些方法和技巧。
????1.對象的生成和大小的調整。
????JAVA程式設計中一個普遍的問題就是沒有好好的利用JAVA語言本身提供的函數,從而常常會生成大量的對象(或實例)。由於系統不僅要花時間生成對象,以後可能還需花時間對這些對象進行垃圾回收和處理。因此,生成過多的對象將會給程式的性能帶來非常大的影響。
????例1:關於String ,StringBuffer,+和append
????JAVA語言提供了對於String類型變量的操作。但如果使用不當,會給程式的性能帶來影響。如下面的語句:
????String name=new String(“HuangWeiFeng”);
????System.out.println(name+”is my name”);
????看似已非常精簡了,其實並非如此。為了生成二進制的代碼,要進行如下的步驟和操作:
????(1) 生成新的字符串 new String(STR_1);
????(2) 複製該字符串;
????(3) 加載字符串常量”HuangWeiFeng”(STR_2);
????(4) 調用字符串的構架器(Constructor);
????(5) 保存該字符串到數組中(從位置0開始);
????(6) 從java.io.PrintStream類中得到靜態的out變量;
????(7) 生成新的字符串緩衝變量new StringBuffer(STR_BUF_1);
????(8) 複製該字符串緩衝變量;
????(9) 調用字符串緩衝的構架器(Constructor);
????(10) 保存該字符串緩衝到數組中(從位置1開始);
????(11) 以STR_1為參數,調用字符串緩衝(StringBuffer)類中的append方法;
????(12) 加載字符串常量”is my name”(STR_3);
????(13) 以STR_3為參數,調用字符串緩衝(StringBuffer)類中的append方法;
????(14) 對於STR_BUF_1執行toString命令;
????(15) 調用out變量中的println方法,輸出結果。
????由此能看出,這兩行簡單的代碼,就生成了STR_1,STR_2,STR_3,STR_4和STR_BUF_1五個對象變量。這些生成的類的實例一般都存放在堆中。堆要對所有類的超類,類的實例進行初始化,同時還要調用類極其每個超類的構架器。而這些操作都是非常消耗系統資源的。因此,對對象的生成進行限制,是完全有必要的。
????經修改,上面的代碼能用如下的代碼來替換。
????StringBuffer name=new StringBuffer(“HuangWeiFeng”);
????System.out.println(name.append(“is my name.”).toString());
????系統將進行如下的操作:
????(1) 生成新的字符串緩衝變量new StringBuffer(STR_BUF_1);
????(2) 複製該字符串緩衝變量;
????(3) 加載字符串常量”HuangWeiFeng”(STR_1);
????(4) 調用字符串緩衝的構架器(Constructor);
????(5) 保存該字符串緩衝到數組中(從位置1開始);
????(6) 從java.io.PrintStream類中得到靜態的out變量;
????(7) 加載STR_BUF_1;
????(8) 加載字符串常量”is my name”(STR_2);
????(9) 以STR_2為參數,調用字符串緩衝(StringBuffer)實例中的append方法;
????(10) 對於STR_BUF_1執行toString命令(STR_3);
????(11)調用out變量中的println方法,輸出結果。
????由此能看出,經過改進後的代碼只生成了四個對象變量:STR_1,STR_2,STR_3和STR_BUF_1.你可能覺得少生成一個對象不會對程式的性能有非常大的提高。但下面的代碼段2的執行速度將是代碼段1的2倍。因為代碼段1生成了八個對象,而代碼段2隻生成了四個對象。
????代碼段1:
????String name= new StringBuffer(“HuangWeiFeng”);
????name+=”is my”;
????name+=”name”;
????代碼段2:
????StringBuffer name=new StringBuffer(“HuangWeiFeng”);
????name.append(“is my”);
????name.append(“name.”).toString();
????因此,充分的利用JAVA提供的庫函數來優化程式,對提高JAVA程式的性能時非常重要的.其注意點主要有如下幾方面;
????(1) 儘可能的使用靜態變量(Static Class Variables)
????如果類中的變量不會隨他的實例而變化,就能定義為靜態變量,從而使他所有的實例都共享這個變量。
????例:
????public class foo
????{
??????SomeObject so=new SomeObject();
????}
????就能定義為:
????public class foo
????{
??????static SomeObject so=new SomeObject();
????}
????(2) 不要對已生成的對象作過多的改動。
????對於一些類(如:String類)來講,寧願在重新生成一個新的對象實例,而不應該修改已生成的對象實例。
????例:
????String name=”Huang”;
????name=”Wei”;
????name=”Feng”;
????上述代碼生成了三個String類型的對象實例。而前兩個馬上就需要系統進行垃圾回收處理。如果要對字符串進行連接的操作,性能將得更差,因為系統將不得為此生成更多得臨時變量,如上例1所示。
????(3) 生成對象時,要分配給他合理的空間和大小JAVA中的非常多類都有他的默認的空間分配大小。對於StringBuffer類來講,默認的分配空間大小是16個字符。如果在程式中使用StringBuffer的空間大小不是16個字符,那麼就必須進行正確的初始化。
????(4) 避免生成不太使用或生命周期短的對象或變量。對於這種情況,因該定義一個對象緩衝池。以為管理一個對象緩衝池的開銷要比頻繁的生成和回收對象的開銷小的多。
????(5) 只在對象作用範圍內進行初始化。JAVA允許在代碼的所有地方定義和初始化對象。這樣,就能只在對象作用的範圍內進行初始化。從而節約系統的開銷。
????例:
????SomeObject so=new SomeObject();
????If(x==1) then
????{
??????Foo=so.getXX();
????}
????能修改為:
????if(x==1) then
????{
??????SomeObject so=new SomeObject();
??????Foo=so.getXX();
????}
????2.異常(Exceptions)
????JAVA語言中提供了try/catch來發方便用戶捕捉異常,進行異常的處理。不過如果使用不當,也會給JAVA程式的性能帶來影響。因此,要注意以下兩點:
????(1) 避免對應用程式的邏輯使用try/catch
????如果能用if,while等邏輯語句來處理,那麼就儘可能的不用try/catch語句。
????(2) 重用異常
????在必須要進行異常的處理時,要儘可能的重用已存在的異常對象。以為在異常的處理中,生成一個異常對象要消耗掉大部分的時間。
????3. 線程(Threading)
????一個高性能的應用程式中一般都會用到線程。因為線程能充分利用系統的資源。在其他線程因為等待硬盤或網絡讀寫而 時,程式能繼續處理和運行。不過對線程運用不當,也會影響程式的性能。
????例2:正確使用Vector類
????Vector主要用來保存各種類型的對象(包括相同類型和不同類型的對象)。不過在一些情況下使用會給程式帶來性能上的影響。這主要是由Vector類的兩個特點所決定的。第一,Vector提供了線程的安全保護功能。即使Vector類中的許多方法同步。不過如果你已確認你的應用程式是單線程,這些方法的同步就完全不必要了。第二,在Vector查找存儲的各種對象時,常常要花非常多的時間進行類型的匹配。而當這些對象都是同一類型時,這些匹配就完全不必要了。因此,有必要設計一個單線程的,保存特定類型對象的類或集合來替代Vector類.用來替換的程式如下(StringVector.java):
????public class StringVector
????{
??????private String [] data;
??????private int count;
??????public StringVector()
??????{
????????this(10); // default size is 10
??????}
??????public StringVector(int initialSize)
??????{
????????data = new String[initialSize];
??????}
??????public void add(String str)
??????{
??????// ignore null strings
??????if(str == null) { return; }
??????ensureCapacity(count + 1);
??????data[count++] = str;
??????}
??????private void ensureCapacity(int minCapacity)
??????{
????????int oldCapacity = data.length;
????????if (minCapacity oldCapacity)
????????{
??????????String oldData[] = data;
??????????int newCapacity = oldCapacity * 2;
??????????data = new String[newCapacity];
??????????System.arraycopy(oldData, 0, data, 0, count);
????????}
??????}
??????public void remove(String str)
??????{
??????if(str == null) { return; // ignore null str }
??????for(int i = 0; i count; i++)
??????{
????????// check for a match
????????if(data[i].equals(str))
????????{
??????????System.arraycopy(data,i+1,data,i,count-1); // copy data
??????????// allow previously valid array element be gc�0�7d
??????????data[–count] = null;
??????????return;
????????}
??????}
??????}
??????public final String getStringAt(int index)
??????{
??????if(index 0) { return null; }
??????else if(index count) { return null; // index is # strings }
??????else { return data[index]; // index is good }
??????}
????}
????因此,代碼:
????Vector Strings=new Vector();
????Strings.add(“One”);
????Strings.add(“Two”);
????String Second=(String)Strings.elementAt(1);
????能用如下的代碼替換:
????StringVector Strings=new StringVector();
????Strings.add(“One”);
????Strings.add(“Two”);
????String Second=Strings.getStringAt(1);
????這樣就能通過優化線程來提高JAVA程式的性能。用於測試的程式如下(TestCollection.java):
????import java.util.Vector;
????public class TestCollection
????{
??????public static void main(String args [])
??????{
????????TestCollection collect = new TestCollection();
????????if(args.length == 0)
????????{
??????????System.out.println(“Usage: java TestCollection [ vector | stringvector ]”);
??????????System.exit(1);
????????}
????????if(args[0].equals(“vector”))
????????{
??????????Vector store = new Vector();
??????????long start = System.currentTimeMillis();
??????????for(int i = 0; i 1000000; i++)
??????????{
????????????store.addElement(“string”);
??????????}
??????????long finish = System.currentTimeMillis();
??????????System.out.println((finish-start));
??????????start = System.currentTimeMillis();
??????????for(int i = 0; i 1000000; i++)
??????????{
????????????String result = (String)store.elementAt(i);
??????????}
??????????finish = System.currentTimeMillis();
??????????System.out.println((finish-start));
????????}
????????else if(args[0].equals(“stringvector”))
????????{
??????????StringVector store = new StringVector();
??????????long start = System.currentTimeMillis();
??????????for(int i = 0; i 1000000; i++) { store.add(“string”); }
??????????long finish = System.currentTimeMillis();
??????????System.out.println((finish-start));
??????????start = System.currentTimeMillis();
??????????for(int i = 0; i 1000000; i++) {
????????????String result = store.getStringAt(i);
??????????}
??????????finish = System.currentTimeMillis();
??????????System.out.println((finish-start));
????????}
??????}
????}
????關於線程的操作,要注意如下幾個方面:
????(1) 防止過多的同步
????如上所示,不必要的同步常常會造成程式性能的下降。因此,如果程式是單線程,則一定不要使用同步。
????(2) 同步方法而不要同步整個代碼段
????對某個方法或函數進行同步比對整個代碼段進行同步的性能要好。
????(3) 對每個對象使用多”鎖”的機制來增大並發。
????一般每個對象都只有一個”鎖”,這就表明如果兩個線程執行一個對象的兩個不同的同步方法時,會發生”死鎖”。即使這兩個方法並不共享所有資源。為了避免這個問題,能對一個對象實行”多鎖”的機制。如下所示:
????class foo
????{
??????private static int var1;
??????private static Object lock1=new Object();
??????private static int var2;
??????private static Object lock2=new Object();
??????public static void increment1()
??????{
????????synchronized(lock1)
????????{
??????????var1++;
????????}
??????}
??????public static void increment2()
??????{
????????synchronized(lock2)
????????{
??????????var2++;
????????}
??????}
????}
????4.輸入和輸出(I/O)
????輸入和輸出包括非常多方面,但涉及最多的是對硬盤,網絡或數據庫的讀寫操作。對於讀寫操作,又分為有緩存和沒有緩存的;對於數據庫的操作,又能有多種類型的JDBC驅動器能選擇。但無論怎樣,都會給程式的性能帶來影響。因此,需要注意如下幾點:
????(1) 使用輸入輸出緩衝
????儘可能的多使用緩存。但如果要經常對緩存進行刷新(flush),則建議不要使用緩存。
????(2) 輸出流(Output Stream)和Unicode字符串
當時用Output Stream和Unicode字符串時,Write類的開銷比較大。因為他要實現Unicode到字節(byte)的轉換.因此,如果可能的話,在使用Write類之前就實現轉換或用OutputStream類代替Writer類來使用。
????(3) 當需序列化時使用transient
當序列化一個類或對象時,對於那些原子類型(atomic)或能重建的原素要表識為transient類型。這樣就不用每一次都進行序列化。如果這些序列化的對象要在網絡上傳輸,這一小小的改動對性能會有非常大的提高。
????(4) 使用高速緩存(Cache)
對於那些經常要使用而又不大變化的對象或數據,能把他存儲在高速緩存中。這樣就能提高訪問的速度。這一點對於從數據庫中返回的結果集尤其重要。
????(5) 使用速度快的JDBC驅動器(Driver)
JAVA對訪問數據庫提供了四種方法。這其中有兩種是JDBC驅動器。一種是用JAVA外包的本地驅動器;另一種是完全的JAVA驅動器。具體要使用哪一種得根據JAVA布署的環境和應用程式本身來定。
????5.一些其他的經驗和技巧
????(1) 使用局部變量。
????(2) 避免在同一個類中動過調用函數或方法(get或set)來設置或調用變量。
????(3) 避免在循環中生成同一個變量或調用同一個函數(參數變量也相同)。
????(4) 儘可能的使用static,final,private等關鍵字。
怎麼做JAVA程序性能優化
1)盡量指定類、方法的final修飾符。帶有final修飾符的類是不可派生的,Java編譯器會尋找機會內聯所有的final方法,內聯對於提升Java運行效率作用重大,此舉能夠使性能平均提高50%。
2)盡量重用對象。由於Java虛擬機不僅要花時間生成對象,以後可能還需要花時間對這些對象進行垃圾回收和處理,因此生成過多的對象將會給程序的性能帶來很大的影響。
3)儘可能使用局部變量。調用方法時傳遞的參數以及在調用中創建的臨時變量都保存在棧中速度較快,其他變量,如靜態變量、實例變量等,都在堆中創建速度較慢。
4)慎用異常。異常對性能不利,只要有異常被拋出,Java虛擬機就必須調整調用堆棧,因為在處理過程中創建了一個新的對象。異常只能用於錯誤處理,不應該用來控制程序流程。
5)乘法和除法使用移位操作。用移位操作可以極大地提高性能,因為在計算機底層,對位的操作是最方便、最快的,但是移位操作雖然快,可能會使代碼不太好理解,因此最好加上相應的注釋。
6)盡量使用HashMap、ArrayList、StringBuilder,除非線程安全需要,否則不推薦使用 Hashtable、Vector、StringBuffer,後三者由於使用同步機制而導致了性能開銷。
盡量在合適的場合使用單例。使用單例可以減輕加載的負擔、縮短加載的時間、提高加載的效率,但並不是所有地方都適用於單例。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/295556.html