我相信字符串池在方法完成时放弃了本地字符串
然而:
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比其本地声明更长?
答案 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() );