`

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()得到的时间不对

    在Java编程中,`new Date()` 和 `Calendar.getInstance().getTime()` 都是获取当前系统时间的方法,但有时可能会出现获取到的时间与预期不符的情况。这种问题通常与时区设置、系统时间、Java运行环境以及代码逻辑...

    Java中Calendar类.pdf

    Calendar calendar = Calendar.getInstance(); calendar.set(2015, 9, 1, 20, 10, 30); String str = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()); System.out.println(str); //...

    java的calendar具体用法

    在Java中处理日期和时间非常常见,而`java.util.Calendar`类则是进行此类操作的核心工具之一。`Calendar`类提供了一系列的功能来帮助开发者处理复杂的日期计算问题,比如日期的加减、获取特定日期组件等。 #### 二...

    日历calendar详细代码

    1. **实例化**:由于`Calendar`是抽象类,不能直接实例化,通常我们通过`Calendar.getInstance()`静态方法获取一个具体的`Calendar`实例,如`GregorianCalendar`。 2. **设置日期**:`set`方法用于设置年、月、日、...

    Calendar.java

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

    java对日期的控制

    Calendar c = Calendar.getInstance(); c.setTime(date); int dayOfWeek = c.get(Calendar.DAY_OF_WEEK); // 处理返回结果 switch (dayOfWeek) { case 1: return "星期日"; case 2: return "星期一"; case...

    史上最全java时间类date的处理

    此外,`java.util.Calendar` 类(尤其是它的子类 `java.util.GregorianCalendar`)也常被用来进行日期的计算和操作。 ### 二、获取当前时间 在代码片段第22行中,通过调用 `getNowTime` 方法来获取当前日期。该...

    java 获取上月、一个月最后一天、周一、周日、本月日期

    Calendar c = Calendar.getInstance(); c.add(Calendar.MONTH, -1); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM"); String time = format.format(c.getTime()); ``` 二、获取一个月最后一天 获取一...

    19. android dialog —— 日期和时间选择对话框

    Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); DatePickerDialog ...

    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 之 Date 和 Calendar 实例

    Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getTime().toString()); ``` 2. 修改日期和时间: ```java calendar.set(Calendar.YEAR, 2022); calendar.set(Calendar.MONTH, Calendar...

    Java-Date 类的学习总结.docx

    Calendar time = Calendar.getInstance(); time.clear(); time.set(Calendar.YEAR, year); time.set(Calendar.MONTH, i-1); int day = time.getActualMaximum(Calendar.DAY_OF_MONTH); ``` 2. Calendar 和 Date 的...

    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的实例源码-Calendar万年历.zip

    它不直接用于创建特定日期或时间的实例,而是通过`Calendar.getInstance()`方法获取特定区域设置的`Calendar`实例。例如: ```java Calendar calendar = Calendar.getInstance(); ``` `Calendar`类提供了丰富的API...

    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); ...

    java Calender类 日期的加减.docx

    Calendar c = Calendar.getInstance(); c.set(Calendar.YEAR, 2006); c.set(Calendar.MONTH, 10); c.set(Calendar.DATE, 3); ``` 上面的代码将设置当前日期为 2006 年 11 月 3 日。 获取当前日期 使用 Calendar ...

Global site tag (gtag.js) - Google Analytics