2009-12-14 26 views
0

我相信字符串池中拋棄本地字符串時,他們的方法完成字符串池是否需要本地變量?

然而:

public class TestPool implements Runnable{ 

    /** 
    * @param args the command line arguments 
    */ 
    public void run() { 
     String str= "hello"; 
     synchronized(str){ 

      try { 
       System.out.print(Thread.currentThread().getName()); 
       Thread.sleep(500); 
       System.out.print(Thread.currentThread().getName()); 
      } 

      catch(InterruptedException e){ 

      } 

     } 
     } 
     public static void main(String []args){ 
      new Thread(new TestPool(),"A").start(); 
      new Thread(new TestPool(),"B").start(); 
     } 
    } 

按照whizlabs指南,基於本地String此代碼正確地將其同步線程。輸出將始終爲AABB或BBAA。爲什麼?爲什麼str字符串超過了它的本地聲明?

回答

3

因爲str的兩個局部聲明都指向相同的實際字符串文字「hello」。 Interned字符串是常量並保存在池中。它們沒有典型的生命週期,因此在沒有參考時不會收集垃圾。

這不會是,如果聲明是

String str = new String("hello"); 
2

str是一個局部變量,其範圍僅限於它定義的run()方法。對於不同的線程,應該有不同的str s。

然而,這兩個不同的本地str s的字符串「Hello」,其作爲一個編譯時間常數,是點的實習。也就是說,具有該內容的String的單個實例在池中生成,並且指向同一個字符運行的任何內容都將指向同一個對象。

就好像你已經創建了一個這樣的String的靜態實例。

+0

+1(更新) - 馬上回來!「? – 2009-12-14 16:02:45

+0

我應該多寫一遍:)希望我的最終文本也值得投票。 – 2009-12-14 16:06:02

+0

引用是一個局部變量,但它指向的字符串不是。查看將聲明更改爲String str = new(「hello」)時會發生什麼? – andandandand 2009-12-14 16:24:50

3

是的,str只是一個局部變量,但它指向字符串池;在該方法的兩次連續調用中,str將指向池中的相同位置,因此您仍在同一個對象上同步。

如果你的代碼是

String str = new String("hello"); 

那麼你會的確可以同步本地對象。

0

這不是字符串池中正在局部變量,它是"hello"只存儲一次,重複使用(因爲字符串是不可變的)的情況。

在您的同步塊內嘗試此操作,兩個線程都將打印相同的值,表明您具有相同的對象。

System.out.println(str.hashCode()); 
+0

我認爲你是自相矛盾的。 「hello」字符串存儲在字符串池中。沒有其他地方可以存儲。 – andandandand 2009-12-14 16:27:25

+0

對於同一對象的測試,hashCode不可靠。 ... 1)不同的字符串可以產生相同的hashCode(「10」和「0O」)... 2)具有相同內容(a.equals(b))的2個不同的字符串(a!= b)必須返回相同的hashCode – 2009-12-14 18:02:05

相關問題