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
测试结果:
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