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

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

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

    一個(gè)關(guān)于StringBuilder與StringBuffer性能的小試驗(yàn)

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

    ?

    試驗(yàn)設(shè)計(jì):

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

    ?

    測(cè)試環(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)行程序時(shí)沒(méi)有為 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));

    ??? }

    ?

    ?

    測(cè)試結(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

    ?

    下面我們將對(duì)測(cè)試程序做一點(diǎn)點(diǎn)小小的改動(dòng),在 new 一個(gè)新的 StringBuffer/StringBuilder 時(shí),我們指定一個(gè)容量參數(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));

    ??? }

    ?

    測(cè)試結(jié)果:(表格中第一,二組為上一輪測(cè)試的結(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)造方法所帶來(lái)的性能提升, StringBuffer 提升了 175.02 %, StringBuilder 提升了 193.70% 。原因在于不指定 StirngBuffer/StringBuilder 的容量時(shí),它們內(nèi)部的字符緩沖區(qū)為 16 個(gè)字符(無(wú)參構(gòu)造)或字符串參數(shù)的長(zhǎng)度,當(dāng)程序不斷的進(jìn)行 append/insert 操作時(shí),每當(dāng)字符數(shù)超過(guò)原有的容量后, StringBuffer/StringBuilder 將不斷的進(jìn)行自動(dòng)擴(kuò)展的工作,這將消耗比較多的時(shí)間。

    ?

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

    ?

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

    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));

    ??? }??

    ?

    測(cè)試結(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 時(shí)應(yīng)盡可能指定它的容量。當(dāng)然,如果你操作的字符串長(zhǎng)度不超過(guò) 16 個(gè)字符就不用了。

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

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

    ?

    特別聲明:

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

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

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

    posted on 2007-02-20 21:56 Tom 閱讀(2290) 評(píng)論(5)  編輯  收藏 所屬分類: Java

    評(píng)論

    # re: 一個(gè)關(guān)于StringBuilder與StringBuffer性能的小試驗(yàn) 2007-08-12 17:34 dreamstone

    這個(gè)不能這么比的,單線程下比是沒(méi)有意義的。
    只有在多線程下才能比較出兩者的區(qū)別。而且并不是多線程下一定要用stringBuffer
    多線程下并不一定要同步的。比如只讀的情況,多線程就不需要同步。這個(gè)時(shí)候測(cè)試一下stringbuffer和stringbuilder的性能吧。差距明顯的不能再明顯了。
    另外如果多線程的情況不是特別復(fù)雜還可以自己手動(dòng)實(shí)現(xiàn)同步。  回復(fù)  更多評(píng)論   

    # re: 一個(gè)關(guān)于StringBuilder與StringBuffer性能的小試驗(yàn) 2007-09-23 20:49 sitinspring

    看看.  回復(fù)  更多評(píng)論   

    # re: 一個(gè)關(guān)于StringBuilder與StringBuffer性能的小試驗(yàn) 2011-10-10 17:18 路人甲

    都是牛人啊
      回復(fù)  更多評(píng)論   

    # re: 一個(gè)關(guān)于StringBuilder與StringBuffer性能的小試驗(yàn) [未登錄](méi) 2012-02-17 22:02 abc

    而且并不是多線程下一定要用stringBuffer
    多線程下并不一定要同步的。比如只讀的情況,或不是公共資源的情況。  回復(fù)  更多評(píng)論   

    # re: 一個(gè)關(guān)于StringBuilder與StringBuffer性能的小試驗(yàn) [未登錄](méi) 2012-04-16 08:59 icanfly

    @dreamstone
    多線程還比什么,一個(gè)是線程安全的,一個(gè)是非線程安全的,沒(méi)有可比性  回復(fù)  更多評(píng)論   

    <2007年8月>
    2930311234
    567891011
    12131415161718
    19202122232425
    2627282930311
    2345678

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(1)

    隨筆分類(42)

    隨筆檔案(43)

    文章分類

    相冊(cè)

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 一本岛高清v不卡免费一三区| 亚洲午夜福利在线视频| 国产午夜亚洲精品国产成人小说| 久久久久国产精品免费看| 亚洲精品无码专区在线| 亚洲人成片在线观看| 国产l精品国产亚洲区在线观看 | 亚洲第一男人天堂| 99人中文字幕亚洲区| 亚洲精品无码高潮喷水在线| 亚洲欧洲久久久精品| yy6080久久亚洲精品| 国产精品久久免费视频| 日韩视频免费在线| 国产a视频精品免费观看| 7x7x7x免费在线观看| 日韩内射激情视频在线播放免费 | 中文字幕免费视频一| 久久久久久成人毛片免费看| 国产精品网站在线观看免费传媒| 成人无码区免费A∨直播| jzzjzz免费观看大片免费| 国产精品亚洲五月天高清| 精品久久久久久久久亚洲偷窥女厕| 国产亚洲视频在线观看网址| 精品一区二区三区免费观看| 污污网站免费观看| 野花高清在线观看免费3中文| 国产网站免费观看| 亚洲色中文字幕无码AV| 久久亚洲国产成人精品性色| 久久亚洲国产成人影院| 无码的免费不卡毛片视频| 久久精品国产免费| 最新中文字幕免费视频| 免费少妇a级毛片人成网| 亚洲VA中文字幕无码一二三区 | 免费国产成人午夜私人影视| 亚洲五月综合缴情在线观看| 亚洲精品免费在线视频| 亚洲A∨精品一区二区三区下载|