標籤:多線程 drp java
在編寫Java程式時,我們經常需要對某些字串進行拼接,之前我們經常用“+”來拼接,但在Java中如果我們直接使用這種拼接方法,會建立很多String型的對象,這樣一來,系統就會因為過多的String型對象而對伺服器對象和系統效能造成很大的影響。所以,Java中有一種更好的拼接字串的方法:使用StringBuffer或StringBuilder。
一、String和StringBuffer
◎ String :是不可變類,任何對String的改變都會產生新的String對象。
當我們使用String來拼接兩個字串時,我們可以執行下面的幾行代碼:
<span style="font-family:FangSong_GB2312;font-size:18px;">String a ="123";String b = "456";String c = a + b;</span>
這樣拼接出來的字串為:123456。而在程式執行完畢時,我們會發現為了滿足程式執行的需要,系統在執行過程建立了a,b,c三個對象。也就是說,使用String的“+”方法來拼接字串時,會產生很多String類型的新對象,用來滿足程式調用和執行的需要。因此,當建立的對象過多,系統的效能和執行效率會因此而受到影響。
◎ StringBuffer:可變類,任何對它所指代的字串的改變都不會產生新的對象。
使用StringBuffer執行兩個字串相加的操作過程:
<span style="font-family:FangSong_GB2312;font-size:18px;"> StringBuffer sb1 = new StringBuffer(str1); sb1.append(str2); String result1 = sb1.toString();</span>
當這個過程執行完畢,我們所需要的內容只有result1這一個對象,而執行過程中間出現的sb1就已經是記憶體回收的目標了。這樣不僅僅避免了執行過程中建立的多個String對象,而且降低了CPU的利用度。
此時,如果我們要實現sb1,sb2,sb3三個字串的拼接,我們只需要在剛才的基礎上,繼續執行便可:
<span style="font-family:FangSong_GB2312;font-size:18px;">StringBuffer sb2 = new StringBuffer(result1);sb2.append(str3);String result2 = sb2.toString();</span>
這樣,對我們有用的就只有result2對象一個,其中產生的sb2和result1都已經成了系統回收的目標。如果繼續增大字串的數量,系統就會相應地產生若干個StringBuffer和String的垃圾對象。
而Java中的垃圾首先是佔用記憶體的,然後Java的虛擬機器會請記憶體回收的線程來回收這些垃圾,這樣就又會出現CPU的損耗,同事這些垃圾對象產生的時候也會產生系統開銷,所以如果在一個迴圈中使用字串的“+”,導致的系統開銷將是不可忽略和不可估量的。
但是相對於StringBuffer來進行字串串連的話,
<span style="font-family:FangSong_GB2312;font-size:18px;">StringBuffer sb = new StringBuffer();sb.append(str1);sb.append(str2);.....sb.append(strN);String result = sb.toString();</span>
除去中間的一個StringBuffer對象最後會被拋棄掉,其他的都是有效對象,比起上面產生的一對垃圾,提高的效率不是一星半點鐘。
二、StringBuffer和StringBuilder
◎ StringBuffer
StringBuffer:字串變數(Synchronized,即安全執行緒)。如果要頻繁對字串內容進行修改,出於效率考慮最好使用StringBuffer,如果想轉成String類型,可以調用StringBuffer的toString()方法。
StringBuffer 上的主要操作有append和insert方法。
◎ StringBuilder
StringBuilder:字串變數(非安全執行緒)。在內部,StringBuilder對象被當作是一個包含字元序列的變長數組。java.lang.StringBuilder是一個可變的字元序列,是JDK5.0新增的。此類提供一個與 StringBuffer 相容的 API,但不保證同步。該類被設計用作 StringBuffer 的一個簡易替換,用在字串緩衝區被單個線程使用的時候(這種情況很普遍)。
二者比較:
在大部分情況下,對執行速度而言,StringBuilder > StringBuffer。因為前者不需要考慮安全執行緒問題。
三、三兄弟的優缺點
String 類型和StringBuffer的主要效能區別:String是不可變的對象, 因此在每次對String 類型進行改變的時候,都會產生一個新的 String 對象,然後將指標指向新的 String 對象,所以經常改變內容的字串最好不要用 String ,因為每次產生對象都會對系統效能產生影響,特別當記憶體中無引用對象多了以後, JVM 的 GC 就會開始工作,效能就會降低。
使用 StringBuffer 類時,每次都會對 StringBuffer 對象本身進行操作,而不是產生新的對象並改變對象引用。所以多數情況下推薦使用 StringBuffer ,特別是字串對象經常改變的情況下。
在某些特別情況下, String 對象的字串拼接其實是被 Java Compiler 編譯成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度並不會比 StringBuffer 對象慢,例如:
<span style="font-family:FangSong_GB2312;font-size:18px;">String s1 = “This is only a” + “ simple” + “ test”; StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”); </span>
產生 String s1對象的速度並不比 StringBuffer慢。其實在Java Compiler裡,自動做了如下轉換:
Java Compiler直接把上述第一條語句編譯為:
<span style="font-family:FangSong_GB2312;font-size:18px;">String s1 = “This is only a simple test”; </span>
所以速度很快。但要注意的是,如果拼接的字串來自另外的String對象的話,Java Compiler就不會自動轉換了,速度也就沒那麼快了。
因此,如果要操作少量的資料,使用String;
單線程操作大量資料,使用StringBuilder;
多線程操作大量資料,使用StringBuffer。
JAVA中的String三兄弟