String池是否采用局部变量?

时间:2009-12-14 15:55:15

标签: java string multithreading synchronization

我相信字符串池在方法完成时放弃了本地字符串

然而:

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 String比其本地声明更长?

4 个答案:

答案 0 :(得分:3)

是的,str只是一个局部变量,但它指向字符串池;在方法的两次连续调用中,str将指向池中的相同位置,因此您仍在同一对象上进行同步。

如果您的代码是

String str = new String("hello");

那么你确实会在本地对象上进行同步。

答案 1 :(得分:3)

因为str的本地声明都指向相同的interned String literal“hello”。 Interned字符串是常量并在池中维护。它们没有典型的生命周期,因此在没有引用时不会收集垃圾。

如果声明是

,则情况并非如此
String str = new String("hello");

答案 2 :(得分:2)

str是一个局部变量,其范围仅限于它定义的run()方法。对于不同的线程,应该有不同的str

然而,这两个不同的本地str指向字符串“hello”,作为编译时常量, interned 。也就是说,在池中生成具有该内容的String的单个实例,并且指向相同字符集的任何内容都将指向该同一对象。

就好像你已经创建了一个这样的String的静态实例。

答案 3 :(得分:0)

字符串池不是采用局部变量,而是"hello"只存储一次并重复使用(因为字符串是不可变的)。

在synchronized块中尝试此操作,两个线程将打印相同的值,表示您具有相同的对象。

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