整理下java中stringBuilder和stringBuffer兩個類的區別

StringBuilder和StringBuffer這兩個類在動態拼接字符串時經常使用,確定比String的效率和開銷小,這是由於String的對象不會回收哦。java

其實我一直用StringBuilder這個類,由於能夠簡寫爲sb的變量在程序裏很爽,但是後來師兄說web程序特別是高併發的程序中不要用stringbuilder,由於簡單說,stringBuilder不是線程安全的,而StirngBuffer就是線程安全的。從網上看到Stringbuffer中方法大都採用了synchronized的關鍵字修飾。web

來來來,咱們先複習下syncronized的用法,有篇博客寫的挺好的,給個連接 http://leo-faith.iteye.com/blog/177779安全

一、synchronized關鍵字的做用域有二種: 1)是某個對象實例內,synchronized aMethod(){}能夠防止多個線程同時訪問這個對象的synchronized方法(若是一個對象有多個synchronized方法,只要一個線程訪問了其中的一個synchronized方法,其它線程不能同時訪問這個對象中任何一個synchronized方法)。這時,不一樣的對象實例的synchronized方法是不相干擾的。也就是說,其它線程照樣能夠同時訪問相同類的另外一個對象實例中的synchronized方法; 2)是某個類的範圍,synchronized static aStaticMethod{}防止多個線程同時訪問這個類中的synchronized static 方法。它能夠對類的全部對象實例起做用。

 

二、除了方法前用synchronized關鍵字,synchronized關鍵字還能夠用於方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問。用法是: synchronized(this){/*區塊*/},它的做用域是當前對象;

三、synchronized關鍵字是不能繼承的,也就是說,基類的方法synchronized f(){} 在繼承類中並不自動是synchronized f(){},而是變成了f(){}。繼承類須要你顯式的指定它的某個方法爲synchronized方法;

好了,言歸正傳,咱們繼續StringBuffer和StringBuilder的區別。併發

就是說,StringBuffer中全部的方法都要加鎖,因此好多操做看上去都是線性操做的。因此要慢些。app

通常狀況下,速度從快到慢:StringBuilder>StringBuffer>String.當須要在循環中屢次使用字符串拼接時,建議使用StringBuilder或StringBuffer.當數量級在百萬級(這裏可能不許確)時,StringBuilder的速度會體現出來.

如下是實驗數據

final static int ttime = 30000;// 測試循環次數

	public void test(String s) {
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ttime; i++) {
			s += "add";
		}
		long over = System.currentTimeMillis();
		System.out.println(" 操做 " + s.getClass().getName() + " 類型使用的時間爲: " + (over - begin) + " 毫秒 ");
	}

	public void test(StringBuffer s) {
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ttime; i++) {
			s.append("add");
		}
		long over = System.currentTimeMillis();
		System.out.println(" 操做 " + s.getClass().getName() + " 類型使用的時間爲: " + (over - begin) + " 毫秒 ");
	}

	public void test(StringBuilder s) {
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ttime; i++) {
			s.append("add");
		}
		long over = System.currentTimeMillis();
		System.out.println(" 操做 " + s.getClass().getName() + " 類型使用的時間爲: " + (over - begin) + " 毫秒 ");
	}

	// 對 String 直接進行字符串拼接的測試
	public void test2() {
		String s2 = "abadf";
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ttime; i++) {
			String s = s2 + s2 + s2;
		}
		long over = System.currentTimeMillis();
		System.out.println(" 操做字符串對象引用相加類型使用的時間爲: " + (over - begin) + " 毫秒 ");
	}

	public void test3() {
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ttime; i++) {
			String s = "abadf" + "abadf" + "abadf";
		}
		long over = System.currentTimeMillis();
		System.out.println(" 操做字符串相加使用的時間爲: " + (over - begin) + " 毫秒 ");
	}

	public static void main(String[] args) {
		String s1 = "abc";
		StringBuffer sb1 = new StringBuffer("abc");
		StringBuilder sb2 = new StringBuilder("abc");
		Test t = new Test();
		t.test(s1);
		t.test(sb1);
		t.test(sb2);
		t.test2();
		t.test3();
	}

試驗結果以下:

 操做 java.lang.String 類型使用的時間爲: 2432 毫秒 高併發

 操做 java.lang.StringBuffer 類型使用的時間爲: 3 毫秒 工具

 操做 java.lang.StringBuilder 類型使用的時間爲: 3 毫秒 測試

 操做字符串對象引用相加類型使用的時間爲: 6 毫秒 ui

 操做字符串相加使用的時間爲: 1 毫秒 this

把循環次數調的很大,試了用下jconsle來監視內存GC,第一次使用,不太明白,有個博客寫的很好的,有空研究一下

 http://jiajun.iteye.com/blog/810150

再補充一個Jstat的工具 http://xiaolele.iteye.com/blog/592022

/**

*20120516昨天忘看源代碼了

**/

StringBuffer中append方法有不少重載,有synchronized關鍵字沒錯,主要調用的仍是AbstractStringBuilder的super的方法。

public synchronized StringBuffer append(String s)
{
    super.append(s);
    return this;
}

父類的方法爲

public AbstractStringBuilder append(String s) {

	if (s == null)
		s = "null";
	int i = s.length();
	if (i == 0)
		return this;
	int j = count + i;
	if (j > value.length)
		expandCapacity(j);
	s.getChars(0, i, value, count);
	count = j;
	return this;
}

StringBuilder類中的append就沒有同步的關鍵字了。父類的方法基本上差很少。

總結一下,StringBuffer線程安全,內部有synchronized方法,StringBuilder是1.5以後出來的,高併發就不要用了。另外synchronized的使用要熟悉,之後研究下java內存的工具,好比jconsle。

相關文章
相關標籤/搜索