缓存在自动装箱中的作用

时间:2014-04-11 19:00:45

标签: java autoboxing

Effective Java中的第5项Joshua Bloch说避免创建对象池,除非对象的权重非常大,但在jdk源代码中我看到Integer类中的IntergerCache,Long和Font类中的LongCache和CharacterCache。

    public class autobox {

        /**
         * @param args
         */
        public static void main(String[] args) {
            long start=System.nanoTime();
            Integer sum=0;
            sum=sum+94;  //1-- takes most time
            long end=System.nanoTime();
            System.out.println(end-start);
            for(int i=0;i<1000;i++)
                sum=sum+i;
            end=System.nanoTime();
            System.out.println(end-start);  //--2
            sum=0;
            for(int j=5;j<1000;j++)
                sum=sum+j;
            end=System.nanoTime();
            System.out.println(end-start);  //--3
        }
    }

我的机器上的输出(使用Java SE 1.7)

540686
984338
1450849

看起来语句1创建了太多的对象,只是为了创建一个Integer对象!我不明白这背后的原因。虽然文档提到-XX:AutoBoxCacheMax=<size>但我收到错误Unrecognized VM option 'AutoBoxCacheMax=0'。 缓存是否只保留创建的对象而不是创建不必要的对象?

1 个答案:

答案 0 :(得分:0)

您无法控制所测量的内容。请在how to do a correct micro benchmark in java上查看。

1)在你的代码中你有:

1      long start=System.nanoTime();
2      Integer sum=0;
3      sum=sum+94;  //1-- takes most time
4      long end=System.nanoTime();

你假设第3行需要花费很多时间。实际上它是第2行(见下文)。

2)你System.out.println(...)包含在2.和3.时间测量中。这是一个问题,因为打印到控制台非常昂贵,应该从测量中消除。

为了说明我重新安排了您的代码并采取了完全不同的措施:

    long start;
    long end;

    start=System.nanoTime();
    System.out.println("println test");
    end = System.nanoTime();
    System.out.println("Time 1: " + (end - start));

    start=System.nanoTime();
    Integer sum=0;
    end = System.nanoTime();
    System.out.println("Time 2: " + (end - start));

    start=System.nanoTime();
    sum=sum+94;
    end = System.nanoTime();
    System.out.println("Time 3: " + (end - start));

    start=System.nanoTime();
    for(int i=0;i<1000;i++) {
        sum=sum+i;
    }
    end = System.nanoTime();
    System.out.println("Time 4: " + (end - start));

    sum=0;
    start=System.nanoTime();
    for(int j=5;j<1000;j++) {
        sum=sum+j;
    }
    end=System.nanoTime();

    System.out.println("Time 5: " + (end - start));

输出:

println test
Time 1: 140572
Time 2: 360759
Time 3: 3420
Time 4: 139639
Time 5: 130619

然后,请不要过多地阅读这些数字。这是一个没有popper预热阶段的测试,没有考虑JIT编译等的影响。