新手學JAVA(三)----StringBuilder類

weixin_33766168發表於2015-03-30

   上一篇文章新手學JAVA(二)----String類與StringBuffer類的區別中瞭解到,String的值是不可變的,這就導致

每次對String的操作都會生成新的String物件,不僅效率低下,而且大量浪費有限的記憶體空間,StringBuffer是可變

類,和執行緒安全的字串操作類,任何對它指向的字串的操作都不會產生新的物件。

   

  StringBuffer類和StringBuilder類功能基本相似。算是兩個雙胞胎。

  下面主要說兩點


  第一點  執行緒安全

  StringBuffer  執行緒安全

  StringBuilder 執行緒不安全


  關於執行緒安全的知識,正在學習,剛接觸,沒有太深入的瞭解,在這知識稍微的提一下。


  執行緒安全——如果你的程式碼所在的程式中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段程式碼。如果每次

執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。


  StringBuffer類和StringBuilder類兩者沒有很大的區別,但是線上程安全方面,StringBuffer允許多執行緒進行字

符操作。這是因為在原始碼中StringBuffer的很多方法都被關鍵字synchronized(這個關鍵字是為執行緒同步機制設定

的。) 修飾了,而StringBuilder沒有。


  簡單的說一說synchronized的含義:

  每一個類物件都對應一把鎖,當某個執行緒A呼叫類物件O中的synchronized方法M時,必須獲得物件O的鎖才能夠執行

M方法,否則執行緒A阻塞。一旦執行緒A開始執行M方法,將獨佔物件O的鎖。使得其它需要呼叫O物件的M方法的執行緒阻

塞。只有執行緒A執行完畢,釋放鎖後。那些阻塞執行緒才有機會重新呼叫M方法。這就是解決執行緒同步問題的鎖機制。


  因此,多執行緒程式設計中StringBuffer比StringBuilder要安全的多。


  有一點需要注意的是,有的人會問,String類是不是也不安全? 事實上不存在這個問題,String是不可變的。線

程對於堆中指定的一個String物件只能讀取,無法修改。還有什麼不安全的?


  第二點  效率問題

  一般情況下,速度從快到慢:StringBuilder>StringBuffer>String,這種比較是相對的,不是絕對的。

  舉個簡單的例子:  

public class TestCharacter{
	final static int time=100;  //迴圈次數
	
	public TestCharacter(){
		
		}
	
	public void test(String s){
		long begin = System.currentTimeMillis();
		for(int i=0;i<time;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<time; i++){ 
			s.append("add"); 
		} 
		long over = System.currentTimeMillis(); 
		System.out.println("操作"+s.getClass().getCanonicalName()+"型別使用的時間為:"+(over-begin)+"毫秒"); 

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

	/*對 String 直接進行字串拼接的測試*/ 
	public void test2(){ 
		String s2 = "abcd"; 
		long begin = System.currentTimeMillis(); 
		for(int i=0; i<time; 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<time; i++){ 
			String s ="abcd" + "abcd" + "abcd"; 
		} 
		long over = System.currentTimeMillis(); 
		System.out.println("操作字串相加使用的時間為:"+(over-begin)+"毫秒"); 
	} 
	
	public static void main(String[] args){ 
		String s1 = "abcd"; 
		StringBuffer st1 = new StringBuffer("abcd"); 
		StringBuilder st2 = new StringBuilder("abcd"); 
		TestCharacter tc = new TestCharacter(); 
		tc.test(s1); 
		tc.test(st1); 
		tc.test(st2); 
		tc.test2(); 
		tc.test3(); 
	} 

}

  下面是迴圈50000次,10000次,1000次,100次的執行結果:

   

   

  總結 

 
  (1).如果要操作少量的資料用 = String

  (2).單執行緒操作字串緩衝區 下操作大量資料 = StringBuilder

  (3).多執行緒操作字串緩衝區 下操作大量資料 = StringBuffer 

相關文章