<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-8  評論-39  文章-0  trackbacks-0

    StringBuilder 是從 Java 5 以后增加的一個字符串處理類。查看 API 文檔,我們可以知道 StringBuilder StringBuffer 提供同樣的功能,只是 StringBuilder 不保證線程安全,所以性能比 StirngBuffer 好,并推薦在確定線程安全的情況下,盡量用 StringBuilder 。事實真是如此嗎?讓我們通過一個小試驗來看看

    ?

    試驗設(shè)計:

    分別用 StringBuilder StringBuffer 將一指定的字符串自連接一百萬次,比較兩種方法所用的時間。為盡量避免環(huán)境的干擾,測試時會關(guān)閉本機(jī)中其它應(yīng)用程序,并且為了避免測試組之間的相互干擾,在每組測試完成后會重起機(jī)器。每個程序運(yùn)行十次,最后取平均值。

    ?

    測試環(huán)境:

    CPU: Celeron – M420

    RAM: 1G

    OS: Window XP Home Edition

    JDK: Sun JDK 1.6.0 (Java HotSpot? Client VM (build 1.6.0-b105, mixed mode, sharing))

    運(yùn)行程序時沒有為 JVM 指定任何參數(shù),全部使用默認(rèn)值

    ?

    程序段:

    1.? StringBuffer

    ?

    ??? private static final int COUNT = 1000000;

    ??? private static final String TEMPLATE = "0123456789" ;

    ??? public static void useStringBuffer() {

    ?????? StringBuffer bf = new StringBuffer( "" );

    ?????? String target = null ;

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

    ?????? for ( int i = 0; i < COUNT ; i++) {

    ?????????? bf.append( TEMPLATE );

    ?????? }

    ?????? target = bf.toString();

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

    ?????? System. out .println( "Use StringBuffer, time is " + (end - start));

    ??? }??

    ?

    ?

    2.? StringBuilder

    ?

    ??? private static final int COUNT = 1000000;

    ??? private static final String TEMPLATE = "0123456789" ;

    ??? public static void useStringBuilder() {

    ?????? StringBuilder bf = new StringBuilder( "" );

    ?????? String target = null ;

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

    ?????? for ( int i = 0; i < COUNT ; i++) {

    ?????????? bf.append( TEMPLATE );

    ?????? }

    ?????? target = bf.toString();

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

    ?????? System. out .println( "Use StringBuilder, time is " + (end - start));

    ??? }

    ?

    ?

    測試結(jié)果:

    ?

     

    StringBuffer

    StringBuilder

    1

    328

    328

    2

    344

    312

    3

    328

    328

    4

    344

    312

    5

    344

    328

    6

    344

    312

    7

    328

    328

    8

    344

    312

    9

    343

    328

    10

    344

    328

    平均值

    339.1

    321.6

    ?

    從結(jié)果中可以看出兩者的性能差異約為 5.44

    ?

    下面我們將對測試程序做一點點小小的改動,在 new 一個新的 StringBuffer/StringBuilder 時,我們指定一個容量參數(shù)。修改的代碼如下:

    ?

    1.? StringBuffer

    ?

    ??? private static final String TEMPLATE = "0123456789" ;

    ??? private static final int COUNT = 1000000;

    ??? public static void useStringBuffer() {

    ?????? StringBuffer bf = new StringBuffer(COUNT * TEMPLATE.length());

    ?????? String target = null ;

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

    ?????? for ( int i = 0; i < COUNT ; i++) {

    ?????????? bf.append( TEMPLATE );

    ?????? }

    ?????? target = bf.toString();

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

    ?????? System. out .println( "Use StringBuffer, time is " + (end - start));

    ??? }??

    ?

    2. StringBuilder

    ?

    ??? private static final String TEMPLATE = "0123456789" ;

    ??? private static final int COUNT = 1000000;

    ??? public static void useStringBuilder() {

    ?????? StringBuilder bf = new StringBuilder(COUNT * TEMPLATE.length());

    ?????? String target = null ;

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

    ?????? for ( int i = 0; i < COUNT ; i++) {

    ?????????? bf.append( TEMPLATE );

    ?????? }

    ?????? target = bf.toString();

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

    ?????? System. out .println( "Use StringBuilder, time is " + (end - start));

    ??? }

    ?

    測試結(jié)果:(表格中第一,二組為上一輪測試的結(jié)果)

    ?

     

    StringBuffer

    StringBuilder

    StringBuffer(int)

    StringBuilder(int)

    1

    328

    328

    140

    94

    2

    344

    312

    125

    125

    3

    328

    328

    125

    93

    4

    344

    312

    125

    125

    5

    344

    328

    109

    94

    6

    344

    312

    125

    110

    7

    328

    328

    125

    110

    8

    344

    312

    110

    110

    9

    343

    328

    140

    109

    10

    344

    328

    109

    125

    平均值

    339.1

    321.6

    123.3

    109.5

    ?

    從表中可以看到 StringBuffer(int) StringBuilder(int) 兩者之間的差異為 12.6% 。但我們更應(yīng)該看到采用不同的構(gòu)造方法所帶來的性能提升, StringBuffer 提升了 175.02 %, StringBuilder 提升了 193.70% 。原因在于不指定 StirngBuffer/StringBuilder 的容量時,它們內(nèi)部的字符緩沖區(qū)為 16 個字符(無參構(gòu)造)或字符串參數(shù)的長度,當(dāng)程序不斷的進(jìn)行 append/insert 操作時,每當(dāng)字符數(shù)超過原有的容量后, StringBuffer/StringBuilder 將不斷的進(jìn)行自動擴(kuò)展的工作,這將消耗比較多的時間。

    ?

    也許有人會說這樣的測試并不能反映真實的情況,因為在實際的開發(fā)中很少會在一個方法中構(gòu)造 / 拼接一個長度為 10*1000000 的字符串的。更通常的情況是在一個方法中構(gòu)造一個不太長的串,但該方法將被大量的,反復(fù)的調(diào)用。 OK, 我們可以修改一下測試程序來放映這種情況。

    ?

    新程序中 contactWith…. 方法用來拼接一個不太長的字符串,該方法被 use…. 方法反復(fù)調(diào)用十萬次,并記錄總的調(diào)用時間。程序如下:

    1.? 使用 StringBuffer

    ?

    ??? private static final String TEMPLATE = "0123456789" ;

    ??? private static final int COUNT = 100000;

    ??? private static final int COUNT2 = 10;

    ??? public static String contactWithStringBuffer() {

    //???? StringBuffer bf = new StringBuffer("");

    ?????? StringBuffer bf = new StringBuffer( COUNT2 * TEMPLATE .length());

    ?????? for ( int i = 0; i < COUNT2 ; i++) {

    ?????????? bf.append( TEMPLATE );

    ?????? }

    ?????? return bf.toString();

    ??? }

    ???

    ??? public static void useStringBuffer() {

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

    ?????? for ( int i = 0; i < COUNT ; i++) {

    ?????????? contactWithStringBuffer();

    ?????? }

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

    ?????? System. out .println( "Use StringBuffer, Time is " + (end - start));

    ??? }

    ?

    2.? 使用 StringBuilder

    ?

    ??? private static final String TEMPLATE = "0123456789" ;

    ??? private static final int COUNT = 100000;

    ??? private static final int COUNT2 = 10;

    ??? public static String contactWithStringBuilder() {

    //???? StringBuilder bf = new StringBuilder("");

    ?????? StringBuilder bf = new StringBuilder( COUNT2 * TEMPLATE .length());

    ?????? for ( int i = 0; i < COUNT2 ; i++) {

    ?????????? bf.append( TEMPLATE );

    ?????? }

    ?????? return bf.toString();

    ??? }

    ???

    ??? public static void useStringBuilder() {

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

    ?????? for ( int i = 0; i < COUNT ; i++) {

    ?????????? contactWithStringBuilder();

    ?????? }

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

    ?????? System. out .println( "Use StringBuilder, Time is " + (end - start));

    ??? }??

    ?

    測試結(jié)果:

    ?

     

    StringBuffer

    StringBuilder

    StringBuffer(int)

    StringBuilder(int)

    1

    188

    156

    140

    109

    2

    187

    172

    141

    125

    3

    188

    172

    125

    110

    4

    188

    172

    141

    110

    5

    187

    172

    125

    110

    6

    188

    172

    125

    109

    7

    172

    172

    125

    125

    8

    188

    157

    125

    110

    9

    203

    172

    125

    110

    10

    188

    172

    125

    109

    平均值

    187.7

    168.9

    129.7

    112.7

    ?

    在這種情況下, StringBuffer StringBuilder 的性能差別為: 11.13% 15.08% (使用 int 構(gòu)造函數(shù));而用不同的構(gòu)造函數(shù)的性能差差異分別達(dá)到: 44.71% StringBuffer )和 49.87% StringBuilder )。并且為 StringBuffer 指定容量(使用 StirngBuffer(int) )比不指定容量的 StringBuilder 的性能高出 30.22%

    ?

    結(jié)論:

    1.? 為了獲得更好的性能,在構(gòu)造 StirngBuffer StirngBuilder 時應(yīng)盡可能指定它的容量。當(dāng)然,如果你操作的字符串長度不超過 16 個字符就不用了。

    2.? 相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風(fēng)險。而在現(xiàn)實的模塊化編程中,負(fù)責(zé)某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環(huán)境中運(yùn)行,因此:除非你能確定你的系統(tǒng)的瓶頸是在 StringBuffer 上,并且確定你的模塊不會運(yùn)行在多線程模式下,否則還是用 StringBuffer J

    3.? 用好現(xiàn)有的類比引入新的類更重要。很多程序員在使用 StringBuffer 時是不指定其容量的(至少我見到的情況是這樣),如果這樣的習(xí)慣帶入 StringBuilder 的使用中,你將只能獲得 10 %左右的性能提升(不要忘了,你可要冒多線程的風(fēng)險噢);但如果你使用指定容量的 StringBuffer ,你將馬上獲得 45% 左右的性能提升,甚至比不使用指定容量的 StirngBuilder 都快 30% 左右。

    ?

    特別聲明:

    1 .本人是基于 Window XP 環(huán)境,用 Sun JDK 1.6 完成的以上測試。測試的結(jié)果是否能反映其它操作系統(tǒng)(如 Linux, Unix 等)和不同的 JDK (IBM, Weblogic ) 的情況就不得而知,有興趣的網(wǎng)友可以在不同的環(huán)境中測試,歡迎您告訴我測試結(jié)果。

    2 .本人也歡迎對本測試的試驗設(shè)計和樣例代碼的合理性和完備性進(jìn)行討論,但請就事論事。不要扔磚頭(西紅柿是可以的,不過不要壞的;雞蛋也可以,但不要臭的,呵呵)

    3 .今天是情人節(jié),祝大家節(jié)日快樂,有情人終成眷屬!

    posted on 2007-02-14 08:00 Jini 閱讀(1885) 評論(14)  編輯  收藏 所屬分類: JDK相關(guān)

    評論:
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-14 10:42 | alysa
    Please help to answer the question as below,
    What method should class extending String override?
      回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗[未登錄] 2007-02-14 11:08 | jini
    @alysa

    The String is final class, no class can be extend it.

    hehe... I am not sure I answer your question. If no, please give me more detail about your question.  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-14 13:36 | cuiyi
    頂一個!希望以后能再次看到你的好貼!  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-14 13:51 | Jini
    @cuiyi

    謝謝你的鼓勵 :)

    其實我只是把日常工作和學(xué)習(xí)的心得體會紀(jì)錄下來與大家分享,希望大家能共同學(xué)習(xí),共同進(jìn)步,呵呵。
      回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-15 08:40 | 不好說
    StringBuffer和StringBuilder在toString這個方法上處理不一樣。

    StringBuffer主要用于在多線程并發(fā)存貯同一個實例上才有優(yōu)勢以。
    web編程很少出現(xiàn)這種情況。
      回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗[未登錄] 2007-02-15 10:21 | jini
    謝謝你的回復(fù)!

    如果是局部變量,應(yīng)該不存在線程安全的問題。但可能會面臨重復(fù)構(gòu)造對象的問題,就像每次調(diào)用contactWith....方法都會構(gòu)造一個新的StringBuffer或StringBuilder,為避免構(gòu)造大量的對象,可能會考慮一些簡單的重用對象的方法,這時就有可能引入多線程的問題了。  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-15 19:18 | BeanSoft
    博主這種認(rèn)真的態(tài)度偶太敬佩了!!! 現(xiàn)在的大牛們總是隨口就是優(yōu)化, 性能, 集群, Cache ... 唉, 不知道他們自己試過了沒.  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-15 20:23 | 喜來了
    其實StringBuilder就是刪除StringBuffer的synchronized定義的一個新類, 在單一線程的情況,兩者的差別取決synchronized和非synchronized函數(shù)的差別. 由于Java的線程是native的, 應(yīng)該和操作系統(tǒng)很有關(guān)系。按摟主(初來乍到,不知道怎么稱呼,叫錯了勿怪)的測試,在Windows XP下相差不大,不知道在其他系統(tǒng)下怎么樣。  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-15 21:02 | Jini
    @BeanSoft

    謝謝你的回復(fù)! 以后有機(jī)會多交流 - Good Good Study, Day Day Up :)

      回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-02-15 21:09 | Jini
    @喜來了

    謝謝你的回復(fù)! 你分析的有道理,不過我沒有在其它環(huán)境測試過,有時間補(bǔ)上,說不定又有些不同的認(rèn)識了,呵呵.....  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗[未登錄] 2007-02-16 21:22 | nake
    認(rèn)真仔細(xì)的程序員重視能令人佩服和值得尊重.  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-03-17 11:00 | kun
    非常嚴(yán)謹(jǐn)直觀的對比。
    感謝分享。  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2007-03-17 13:12 | kun
    請教:
    1.如果測試時StringBuilder和String執(zhí)行的不是附加,而是循環(huán)賦新值操作呢?
    (StringBuilder必須通過replace或者先delete再附加來實現(xiàn)重新賦值?)
    2.聲明一個String和聲明一個StringBuilder再toString哪個開銷比較大?  回復(fù)  更多評論
      
    # re: 一個關(guān)于StringBuilder與StringBuffer性能的小試驗 2011-11-28 21:27 | xinyonda
    mark  回復(fù)  更多評論
      
    主站蜘蛛池模板: 亚洲国产精品18久久久久久 | 黄色网址在线免费观看| 中文在线免费观看| 国产福利视精品永久免费| 免费看国产一级特黄aa大片| 亚洲一区影音先锋色资源| 男人的天堂av亚洲一区2区| 精品无码无人网站免费视频| 亚洲高清国产拍精品青青草原| 亚洲嫩草影院久久精品| 亚洲成色WWW久久网站| 久久久久亚洲AV成人无码| 免费国产在线观看不卡| 久久精品国产亚洲av影院| 亚洲AV综合色区无码一区爱AV | 曰韩亚洲av人人夜夜澡人人爽| 日韩精品免费一区二区三区| 日韩高清免费在线观看| 亚洲国产成人久久精品软件| 成人网站免费看黄A站视频| 激情内射亚洲一区二区三区| 国拍在线精品视频免费观看| 亚洲欧美日韩中文无线码| 无码欧精品亚洲日韩一区夜夜嗨| 亚洲视频在线免费| 99久久亚洲综合精品成人网| 女人18毛片水最多免费观看| 三级片免费观看久久| 91久久精品国产免费一区| 亚洲一区综合在线播放| 午夜免费福利在线| 国产美女视频免费观看的网站| 亚洲尹人九九大色香蕉网站| 黄网址在线永久免费观看| 一级毛片人与动免费观看| 色妞WWW精品免费视频 | 亚洲国产人成网站在线电影动漫| 成人福利免费视频| 五级黄18以上免费看| 久久久国产精品亚洲一区| 国产成人涩涩涩视频在线观看免费|