參考鏈接: Java中的StringBuffer類
StringBuilder和StringBuffer這兩個類在動態拼接字符串時常用,肯定比String的效率和開銷小,這是因為String的對象不會回收哦。?
?其實我一直用StringBuilder這個類,因為可以簡寫為sb的變量在程序里很爽,可是后來師兄說web程序特別是高并發的程序中不要用stringbuilder,因為簡單說,stringBuilder不是線程安全的,而StirngBuffer就是線程安全的。從網上看到Stringbuffer中方法大都采用了synchronized的關鍵字修飾。?
?來來來,我們先復習下syncronized的用法,有篇博客寫的挺好的,給個鏈接 http://leo-faith.iteye.com/blog/177779?
??
?
? 1、synchronized關鍵字的作用域有二種: 1)是某個對象實例內,synchronized aMethod(){}可以防止多個線程同時訪問這個對象的synchronized方法(如果一個對象有多個synchronized方法,只要一個線程訪問了其中的一個synchronized方法,其它線程不能同時訪問這個對象中任何一個synchronized方法)。這時,不同的對象實例的synchronized方法是不相干擾的。也就是說,其它線程照樣可以同時訪問相同類的另一個對象實例中的synchronized方法; 2)是某個類的范圍,synchronized static aStaticMethod{}防止多個線程同時訪問這個類中的synchronized static 方法。它可以對類的所有對象實例起作用。
?
? ?
?
? 2、除了方法前用synchronized關鍵字,synchronized關鍵字還可以用于方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問。用法是: synchronized(this){/*區塊*/},它的作用域是當前對象;
?
?
?
? 3、synchronized關鍵字是不能繼承的,也就是說,基類的方法synchronized f(){} 在繼承類中并不自動是synchronized f(){},而是變成了f(){}。繼承類需要你顯式的指定它的某個方法為synchronized方法;
?
?好了,言歸正傳,我們繼續StringBuffer和StringBuilder的區別。?
?就是說,StringBuffer中所有的方法都要加鎖,所以好多操作看上去都是線性操作的。所以要慢些。?
??
?
? 一般情況下,速度從快到慢:StringBuilder>StringBuffer>String.當需要在循環中多次使用字符串拼接時,建議使用StringBuilder或StringBuffer.當數量級在百萬級(這里可能不準確)時,StringBuilder的速度會體現出來.
?
?
以下是實驗數據?
??
??
?
??
? ?
? ? 01 final static int ttime = 30000;// 測試循環次數?
? ?
? ?
? ? 02? ?
? ?
? ?
? ? 03? ? ?public void test(String s) {?
? ?
? ?
? ? 04? ? ? ? ?long begin = System.currentTimeMillis();?
? ?
? ?
? ? 05? ? ? ? ?for (int i = 0; i < ttime; i++) {?
? ?
? ?
? ? 06? ? ? ? ? ? ?s += "add";?
? ?
? ?
? ? 07? ? ? ? ?}?
? ?
? ?
? ? 08? ? ? ? ?long over = System.currentTimeMillis();?
? ?
? ?
? ? 09? ? ? ? ?System.out.println(" 操作 " + s.getClass().getName() + " 類型使用的時間為: " + (over - begin) + " 毫秒 ");?
? ?
? ?
? ? 10? ? ?}?
? ?
? ?
? ? 11? ?
? ?
? ?
? ? 12? ? ?public void test(StringBuffer s) {?
? ?
? ?
? ? 13? ? ? ? ?long begin = System.currentTimeMillis();?
? ?
? ?
? ? 14? ? ? ? ?for (int i = 0; i < ttime; i++) {?
? ?
? ?
? ? 15? ? ? ? ? ? ?s.append("add");?
? ?
? ?
? ? 16? ? ? ? ?}?
? ?
? ?
? ? 17? ? ? ? ?long over = System.currentTimeMillis();?
? ?
? ?
? ? 18? ? ? ? ?System.out.println(" 操作 " + s.getClass().getName() + " 類型使用的時間為: " + (over - begin) + " 毫秒 ");?
? ?
? ?
? ? 19? ? ?}?
? ?
? ?
? ? 20? ?
? ?
? ?
? ? 21? ? ?public void test(StringBuilder s) {?
? ?
? ?
? ? 22? ? ? ? ?long begin = System.currentTimeMillis();?
? ?
? ?
? ? 23? ? ? ? ?for (int i = 0; i < ttime; i++) {?
? ?
? ?
? ? 24? ? ? ? ? ? ?s.append("add");?
? ?
? ?
? ? 25? ? ? ? ?}?
? ?
? ?
? ? 26? ? ? ? ?long over = System.currentTimeMillis();?
? ?
? ?
? ? 27? ? ? ? ?System.out.println(" 操作 " + s.getClass().getName() + " 類型使用的時間為: " + (over - begin) + " 毫秒 ");?
? ?
? ?
? ? 28? ? ?}?
? ?
? ?
? ? 29? ?
? ?
? ?
? ? 30? ? ?// 對 String 直接進行字符串拼接的測試?
? ?
? ?
? ? 31? ? ?public void test2() {?
? ?
? ?
? ? 32? ? ? ? ?String s2 = "abadf";?
? ?
? ?
? ? 33? ? ? ? ?long begin = System.currentTimeMillis();?
? ?
? ?
? ? 34? ? ? ? ?for (int i = 0; i < ttime; i++) {?
? ?
? ?
? ? 35? ? ? ? ? ? ?String s = s2 + s2 + s2;?
? ?
? ?
? ? 36? ? ? ? ?}?
? ?
? ?
? ? 37? ? ? ? ?long over = System.currentTimeMillis();?
? ?
? ?
? ? 38? ? ? ? ?System.out.println(" 操作字符串對象引用相加類型使用的時間為: " + (over - begin) + " 毫秒 ");?
? ?
? ?
? ? 39? ? ?}?
? ?
? ?
? ? 40? ?
? ?
? ?
? ? 41? ? ?public void test3() {?
? ?
? ?
? ? 42? ? ? ? ?long begin = System.currentTimeMillis();?
? ?
? ?
? ? 43? ? ? ? ?for (int i = 0; i < ttime; i++) {?
? ?
? ?
? ? 44? ? ? ? ? ? ?String s = "abadf" + "abadf" + "abadf";?
? ?
? ?
? ? 45? ? ? ? ?}?
? ?
? ?
? ? 46? ? ? ? ?long over = System.currentTimeMillis();?
? ?
? ?
? ? 47? ? ? ? ?System.out.println(" 操作字符串相加使用的時間為: " + (over - begin) + " 毫秒 ");?
? ?
? ?
? ? 48? ? ?}?
? ?
? ?
? ? 49? ?
? ?
? ?
? ? 50? ? ?public static void main(String[] args) {?
? ?
? ?
? ? 51? ? ? ? ?String s1 = "abc";?
? ?
? ?
? ? 52? ? ? ? ?StringBuffer sb1 = new StringBuffer("abc");?
? ?
? ?
? ? 53? ? ? ? ?StringBuilder sb2 = new StringBuilder("abc");?
? ?
? ?
? ? 54? ? ? ? ?Test t = new Test();?
? ?
? ?
? ? 55? ? ? ? ?t.test(s1);?
? ?
? ?
? ? 56? ? ? ? ?t.test(sb1);?
? ?
? ?
? ? 57? ? ? ? ?t.test(sb2);?
? ?
? ?
? ? 58? ? ? ? ?t.test2();?
? ?
? ?
? ? 59? ? ? ? ?t.test3();?
? ?
? ?
? ? 60? ? ?}?
? ?
??
?
??
試驗結果如下:?
??
??
? 操作 java.lang.String 類型使用的時間為: 2432 毫秒??
? 操作 java.lang.StringBuffer 類型使用的時間為: 3 毫秒??
? 操作 java.lang.StringBuilder 類型使用的時間為: 3 毫秒??
? 操作字符串對象引用相加類型使用的時間為: 6 毫秒??
? 操作字符串相加使用的時間為: 1 毫秒??
??
?把循環次數調的很大,試了用下jconsle來監視內存GC,第一次使用,不太明白,有個博客寫的很好的,有空研究一下?
? http://jiajun.iteye.com/blog/810150?
?再補充一個Jstat的工具 http://xiaolele.iteye.com/blog/592022?
?/**?
?*20120516昨天忘看源代碼了?
?**/?
?StringBuffer中append方法有很多重載,有synchronized關鍵字沒錯,主要調用的還是AbstractStringBuilder的super的方法。?
??
?
??
? ?
? ? 1 public synchronized StringBuffer append(String s)?
? ?
? ?
? ? 2 {?
? ?
? ?
? ? 3? ? ?super.append(s);?
? ?
? ?
? ? 4? ? ?return this;?
? ?
? ?
? ? 5 }?
? ?
??
?
??
父類的方法為?
??
?
??
? ?
? ? 01 public AbstractStringBuilder append(String s) {?
? ?
? ?
? ? 02? ?
? ?
? ?
? ? 03? ? ?if (s == null)?
? ?
? ?
? ? 04? ? ? ? ?s = "null";?
? ?
? ?
? ? 05? ? ?int i = s.length();?
? ?
? ?
? ? 06? ? ?if (i == 0)?
? ?
? ?
? ? 07? ? ? ? ?return this;?
? ?
? ?
? ? 08? ? ?int j = count + i;?
? ?
? ?
? ? 09? ? ?if (j > value.length)?
? ?
? ?
? ? 10? ? ? ? ?expandCapacity(j);?
? ?
? ?
? ? 11? ? ?s.getChars(0, i, value, count);?
? ?
? ?
? ? 12? ? ?count = j;?
? ?
? ?
? ? 13? ? ?return this;?
? ?
? ?
? ? 14 }?
? ?
??
?
??
??
?StringBuilder類中的append就沒有同步的關鍵字了。父類的方法基本上差不多。?
?總結一下,StringBuffer線程安全,內部有synchronized方法,StringBuilder是1.5之后出來的,高并發就不要用了。另外synchronized的使用要熟悉,以后研究下java內存的工具,比如jconsle。?
? ?
?轉載:http://my.oschina.net/zimingforever/blog/57514