String Pool 底层 Hashtable 结构的说明与实战

一 点睛

  • 字符串常量池是不会存储相同内容的字符串的。

  • String 的 String Pool是一个固定大小的 Hashtable,默认值大小长度是1009。如果放进 String Pool 的 String非常多,就会造成 Hash 冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用string.intern时性能会大幅下降。

  • 使用 -XX:StringTableSize 可设置 StringTable 的长度

  • 在 JDK6 中 StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。StringTablesize 设置没有要求。

  • 在 JDK7 中,StringTable 的长度默认值是 60013。

  • 在 JDK8 中,StringTable 可以设置的最小值为1009。

二 实战——StringTableSize值测试

1 代码

/**
* 测试  StringTableSize
*  -XX:StringTableSize=1009
*/
public class StringTest2 {
    public static void main(String[] args) {
        // 测试StringTableSize 参数
        System.out.println("我来打个酱油");
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}

2 JDK6下运行后测试默认值

E:\JVMDemo>jps

1796 Jps

13976

3832 StringTest2

7756 Launcher

E:\JVMDemo>jinfo -flag StringTableSize 3832

-XX:StringTableSize=1009

3 JDK6 下修改为 -XX:StringTableSize=10

E:\JVMDemo>jps

9664 Jps

10532 Launcher

11764 StringTest2

13976

E:\JVMDemo>jinfo -flag StringTableSize 11764

-XX:StringTableSize=10

4 JDK7下运行后测试默认值

E:\JVMDemo>jps

1892 Jps

13976

6984 StringTest2

4012 Launcher

E:\JVMDemo>jinfo -flag StringTableSize 6984

-XX:StringTableSize=60013

5 JDK7 下修改为 -XX:StringTableSize=1000

E:\JVMDemo>jps

13972 StringTest2

5684 Launcher

13976

3180 Jps

E:\JVMDemo>jinfo -flag StringTableSize 13972

-XX:StringTableSize=1000

6 JDK8 下修改为 -XX:StringTableSize=1000

Error: Could not create the Java Virtual Machine.

Error: A fatal exception has occurred. Program will exit.

StringTable size of 1000 is invalid; must be between 1009 and 2305843009213693951

三 实战——StringTableSize性能测试

1 代码——产生10万个长度不超过10的字符串

/**
* 产生10万个长度不超过10的字符串,包含a-z,A-Z
*/
public class GenerateString {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("words.txt");
        for (int i = 0; i < 100000; i++) {
            //1 - 10
            int length = (int) (Math.random() * (10 - 1 + 1) + 1);
            fw.write(getString(length) + "\n");
        }
        fw.close();
    }


    public static String getString(int length) {
        String str = "";
        for (int i = 0; i < length; i++) {
            //65 - 90, 97-122
            int num = (int) (Math.random() * (90 - 65 + 1) + 65) + (int) (Math.random() * 2) * 32;
            str += (char) num;
        }
        return str;
    }
}

2 代码——测试性能

/**
-XX:StringTableSize=1009
* 测试  StringTableSize 不同大小的性能
*/
public class StringTest2 {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("words.txt"));
            long start = System.currentTimeMillis();
            String data;
            while((data = br.readLine()) != null){
                data.intern(); // 如果字符串常量池中没有对应 data 的字符串的话,则在常量池中生成
            }
            long end = System.currentTimeMillis();
            System.out.println("花费的时间为:" + (end - start));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3 当设置为 -XX:StringTableSize=1009

花费的时间为:259

4 当设置为 -XX:StringTableSize=100009

花费的时间为:60

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值