String的intern方法使用场景

2023-12-18 12:35:01 浏览数 (1)

使用场景

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()虽然会有性能影响,但是看你的使用场景。

最后 点赞关注评论一键三连,每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!

0 人点赞