我想在Java中使用String.intern()来节省内存(使用相同内容的字符串的内部池)。我从不同的线程调用此方法。这会有问题吗?
回答你的问题,是的,它是线程安全的。
然而,你可能需要重新考虑使用这个功能来减少内存消耗。原因是你无法从字符串池中删除任何条目。更好的解决方案是创建自己的功能。你只需要将字符串存储在像这样的HashMap<String,String>
中:
public String getInternedString(String s) {
synchronized(strings) {
String found = strings.get(s);
if(found == null) {
strings.put(s, s);
found = s;
}
return found;
}
}
intern
性能。如果我没记错的话,时间复杂度是 O(n),其中 n 是字符串池当前的大小。 - Marko Topolnikif (found == null)
吗?而且,即使 strings
是线程安全的数据结构,按照现在的写法,它也几乎不是线程安全的。 - Ted Hoppsynchronized
块,因为有多种表达方式。显然那是错误的选择,我已经编辑它以包括它。 - Elias MårtensonInterner
(http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Interners.html)。 - Daniel Pryden返回一个不可变的Java-String,该方法是线程安全的。您不能直接操作该字符串。
文档确实表明它是线程安全的(通过强调任何)。
因此,对于任何两个字符串s和t,当且仅当s.equals(t)为真时,s.intern() == t.intern()才为真。
总之,我们有充分的理由说它是线程安全的。
PS:但是,如果您使用多个类加载器,则可能会遇到挑战性的结果,因为String池是按String类维护的。
A pool of strings, initially empty, is maintained privately by the class String.
java.lang.String
只能由引导类加载器加载。 - irreputable
new String("abc") != "abc"
;但是,"ab" + "c" == "abc"
(因为合并)。 - Ted Hopp