使用场景
intern()
方法是 Java 中的一个方法,它用于将字符串对象添加到字符串常量池中,并返回该字符串在常量池中的引用。
当调用 intern()
方法时,如果字符串常量池中已经存在该字符串,则直接返回常量池中的引用;如果常量池中不存在该字符串,则将该字符串添加到常量池中,并返回新添加的字符串引用。
使用 intern()
方法可以节省内存空间,因为它可以使多个字符串对象共享同一个字符串常量池中的实例。这在处理大量字符串对象时特别有用。
以下是一个示例:
代码语言:javascript复制String str1 = new String("Hello");
String str2 = str1.intern();
System.out.println(str1 == str2); // 输出:false
System.out.println(str1.equals(str2)); // 输出:true
在上面的示例中,str1
是通过 new
关键字创建的新的字符串对象,而 str2
是通过 intern()
方法从常量池中获取的引用。尽管它们的内容相同,但它们是不同的对象。通过比较引用地址可以看出,str1 == str2
的结果为 false
,而通过比较内容可以看出,str1.equals(str2)
的结果为 true
。
`intern()` 方法本身并不能防止并发,但是它可以减少内存使用,从而减少内存溢出的可能性,进而提高程序的稳定性。
这个方法是能防止并发的吗
在多线程环境下,如果多个线程同时调用 `intern()` 方法添加同一个字符串到常量池中,那么常量池中只会存在一个该字符串的实例。这样可以减少内存使用,但是需要注意的是,由于多个线程同时访问常量池,可能会导致线程安全问题。因此,在多线程环境下使用 `intern()` 方法时,需要采取相应的同步措施来确保线程安全。
另外,需要注意的是,使用 `intern()` 方法也可能会带来一些性能问题。由于在常量池中查找字符串需要进行哈希计算和比较操作,因此在大量使用 `intern()` 方法时可能会影响程序的性能。因此,在使用 `intern()` 方法时需要根据具体情况进行权衡和优化。
代码示例
代码语言:javascript复制 @Test
public void testString() throws InterruptedException {
String str1 = "hello";
String str2 = new String("hello");
String str3 = new String("hello");
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
System.out.println(str1.intern() == str2);
System.out.println(str2.intern() == str1);
System.out.println(str3.intern() == str2.intern());
Map<String, String> map = new ConcurrentHashMap<>();
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i ) {
int finalI = i;
executorService.execute(()->{
String key = new String("hello" finalI % 2);
String value;
if (Objects.isNull(value = map.get(key))) {
value = key.intern();
map.put(key, value);
}
synchronized (value) {
System.out.println("获得锁:" value);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
System.out.println("释放锁:" value);
}
});
}
Thread.currentThread().join();
}
执行结果
代码语言:javascript复制99162322
99162322
false
true
true
获得锁:hello1
获得锁:hello0
释放锁:hello0
释放锁:hello1
获得锁:hello0
获得锁:hello1
释放锁:hello1
释放锁:hello0
获得锁:hello0
释放锁:hello0
分析总结
当你在进行一个对象锁的时候可以使用这种方式,锁定某个特定的对象,我这个示例其实随意创建一个对象都可以,只要保证每次都取的是唯一的就可以了,借此引出intern()
的部分使用场景。
记得曾经推特的工程师使用intern()
对地址进行内存优化,使得原本相同的地址占用不同的内存问题得到了释放,intern()
虽然会有性能影响,但是看你的使用场景。
最后 点赞关注评论一键三连,每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!