在java的文档中,它说在下面的示例中,条件将为真:
String a = new String("ABC");
String b = new String("ABC");
if (a.intern() == b.intern())
{
....
}
我想知道,考虑到a
时,这是否仍然正确。和b
定义在不同的Threads
中,甚至不同 ClassLoaders
?
当我需要能够同步一个基于实体名称加载特定配置的 block 时,这个问题就出现了,所以我想做一些类似的事情:
synchronized (entityName.intern())
{
}
我不确定这是一个好的做法,所以我可能不会追求这个方向 - 但这个问题仍然让我感兴趣。
最佳答案
如果在不同的线程上,是的,条件将为真。
如果在不同的类加载器上,我不会指望条件为真。 (但是你真的使用不同的类加载器加载 String
的两个副本吗?)文档说 intern
是在 String
中实现的,使用它自己的缓存。来自 String#intern
documentation :
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class
String
.
(我的重点)
因此,如果您以某种方式使用不同的类加载器加载了 String
类两次(我不确定您将如何做到这一点,但我打赌有办法),那么两个 String
理论上,每个类都有自己的缓存。然而,实现可能不会使这一点产生区别。 intern
是 Oracle JVM 中的 native 方法,使用 C++ 实现的符号表。我还没有足够仔细地遵循逻辑,无法确定在您所讨论的边缘情况下,同一 JVM 中的两个 String 实例是否会共享相同的符号表。但到那时,我们正在考虑实现情况,这可能会有所不同。 文档表明不,它们不会是同一个字符串。
关于java - 实习字符串在不同线程和类加载器之间的行为如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9294134/