`

Calendar.getInstance()的坑

阅读更多

Calendar.getInstance()看起来应该是个单例,但实际上并不是。
一次在JProfile中查看CPU的消耗的时候,发现 Calendar.getInstance() 消耗的CPU占比比较大,具体看了下代码才发现实际上是每次都创建对象的。



public static Calendar getInstance(TimeZone zone,
                                       Locale aLocale)
    {
        return createCalendar(zone, aLocale);
    }

private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }



代码中可以清楚的看到是每次都创建的。
那么创建对象的成本怎么样呢?

public static void main(String[] args) {
        int runs = 10000;
        long start = System.nanoTime();
        Calendar cal = null;
        for(int i=0;i<runs;i++)
            cal = Calendar.getInstance();
        long time = System.nanoTime() - start;
        System.out.println("Calendar.getInstance() took on average "+time/runs+" ns. "+cal);

        long start2 = System.nanoTime();
        long now = 0;
        for(int i=0;i<runs;i++)
            now = System.currentTimeMillis();
        long time2 = System.nanoTime() - start2;
        System.out.println("System.currentTimeMillis() took on average "+time2/runs+" ns. "+now);
    }


测试结果:
Calendar.getInstance() took on average 8264 ns. java.util.GregorianCalendar[time=1481014104709,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Chongqing",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=11,WEEK_OF_YEAR=50,WEEK_OF_MONTH=2,DAY_OF_MONTH=6,DAY_OF_YEAR=341,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=4,HOUR_OF_DAY=16,MINUTE=48,SECOND=24,MILLISECOND=709,ZONE_OFFSET=28800000,DST_OFFSET=0]
System.currentTimeMillis() took on average 105 ns. 1481014104711

可以看到是System.currentTimeMillis()的80多倍。性能其实是很差了的。
建议Calendar对象可以缓存起来,不用每次都创建。
具体的讨论在stackoverflow上也有: http://stackoverflow.com/questions/4587878/creating-java-object-general-question





0
0
分享到:
评论

相关推荐

    JAVA new Date()或Calendar.getInstance().getTime()得到的时间不对

    NULL 博文链接:https://ollevere.iteye.com/blog/1320854

    Calendar.java

    格式与电脑日历一致,包括从1970年至今。

    java的calendar具体用法

    实际上,在历史上有着许多种纪元的方法。它们的差异实在太大了,比如说一个...我们从 Calendar.getInstance() 中所获得的实例就是一个 \"GreogrianCalendar\" 对象(与您通过 new GregorianCalendar() 获得的结果一致)。

    JAVA日期操作汇总

    2.Calendar和Date的转化 (1) Calendar转化为Date Calendar cal=Calendar.getInstance(); Date date=cal.getTime(); (2) Date转化为Calendar Date date=new Date(); Calendar cal=Calendar.getInstance(); cal.set...

    Java中Calendar类.pdf

    Java中Calendar类.pdf 学习资料 复习资料 教学资源

    DateUtils.java

    Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month); Date currMonthFirst = calendar.getTime(); return ...

    video_20200224_154733_cps.mp4

    开发过程中,我常常先编写方法,如Calendar.getInstance(),然后通过ctrl+2快捷键将方法的计算结果赋值于一个本地变量之上。 这样我节省了输入类名,变量名以及导入声明的时间。Ctrl+F的效果类似,不过效果是把方法...

    java基础题目 java面试题

    Calendar c = Calendar.getInstance(); //取得年月日,小时分秒 int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH)+1; int day = c.get(Calendar.DATE); int hour = c.get(Calendar....

    jar编写的日程管理系统

    import java.util.Calendar; import java.util.Date; import javax.microedition.rms.RecordStoreException; /* * 创建日期 2006-12-6 * * TODO 要更改此生成的文件的模板,请转至 * 窗口 - 首选项 - Java - ...

    Android系统设置闹钟

    calendar=Calendar.getInstance(); alarmManager=(AlarmManager) getSystemService(ALARM_SERVICE); } public void myclick(View v){ new TimePickerDialog(MainActivity.this, 0, new ...

    Android代码-Android-Skin

    AndroidSkin.getInstance().saveSkinAndApply(skinFilePath, SkinLoader.ASSETS); 执行之后,app即完成换肤,你将看到华丽的换肤效果; Demo Usage 1、在 app/buil.gradle 添加 compile '...

    java时间处理工具类--CalendarUtil(java源码)

    Calendar now = Calendar.getInstance(); now.setTime(date); int today = now.get(Calendar.DAY_OF_WEEK); int first_day_of_week = now.get(Calendar.DATE) + 2 - today; // 星期一 now.set(Calendar....

    android时间控件

    final Calendar c = Calendar.getInstance(); mYear = c.get(Calendar.YEAR); mMonth = c.get(Calendar.MONTH); mDay = c.get(Calendar.DAY_OF_MONTH); mHour = c.get(Calendar.HOUR_OF_DAY); ...

    AESUtil AES的加密和解密java工具类

    KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); Cipher cipher = Cipher.getInstance(ALGORITHMSTR); //"算法/模式/补码方式" SecretKeySpec skeySpec = new SecretKeySpec...

    日历calendar详细代码

    日历calendar详细代码

    javaMessageDigest md5算法详细实现

    public static String md5(String str) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(str.getBytes()); byte b[] = md.digest();

    Java课程设计案例经编

    import java.util.Calendar; class TestClassCalendar{ public static void main(String args[]){ Calendar mycalendar1 = Calendar.getInstance(); System.out.println("今日日期: "); System.out....

    Java课程设计案例精编

    import java.util.Calendar; class TestClassCalendar{ public static void main(String args[]){ Calendar mycalendar1 = Calendar.getInstance(); System.out.println("今日日期: "); System.out....

    java2 使用教程(第三版) 实验指导 上机实践5 字符串、时间与数字

    Calendar calendar = Calendar.getInstance(); calendar.set(yearOne,monthOne-1,dayOne); long timeOne = calendar.getTimeInMillis(); calendar.set(yearTwo,monthTwo-1,dayTwo); long timeTwo = calendar....

    calendar.java

    使用java.util.Calendar类,通过Calendar.getInstance()可以获得当前系统的日期和时间; 通过Calendar对象的set()方法可以修改Calendar对象的年月日等信息; 通过Calendar对象的get(Calendar.DAY_OF_WEEK)方法可以...

Global site tag (gtag.js) - Google Analytics