System.currentTimeMillis()与新Date()与Calendar.getInstance()。getTime()


239

在Java中,使用的性能和资源含义是什么?

System.currentTimeMillis() 

new Date() 

Calendar.getInstance().getTime()

据我了解,System.currentTimeMillis()是最有效的。但是,在大多数应用程序中,该长值需要转换为Date或某个类似的对象才能对人类有意义。

Answers:


242

System.currentTimeMillis()显然,它是最有效的,因为它甚至不创建任何对象,但new Date()实际上只是一个很长的薄包装,因此紧随其后。Calendar另一方面,它相对较慢且非常复杂,因为它必须处理日期和时间固有的相当大的复杂性和所有奇数(ap年,夏时制,时区等)。

通常,最好只处理Date应用程序中的较长时间戳或对象,并且仅Calendar在实际需要执行日期/时间计算或格式化日期以将其显示给用户时使用,才是一个好主意。如果您需要执行很多操作,则使用Joda Time可能是一个好主意,因为它具有更干净的界面和更好的性能。


2
timestamp和currentMillis有什么区别?
pinkpanther

1
@pinkpanther:“时间戳记”通常用于描述整数/长整数,当被解释为自“历元开始”以来的秒或毫秒时,它描述了一个时间点。换句话说,currentTimeMillis()返回一个时间戳。
Michael Borgwardt '18

43

查看JDK,最里面的构造函数Calendar.getInstance()具有以下功能:

public GregorianCalendar(TimeZone zone, Locale aLocale) {
    super(zone, aLocale);
    gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone);
    setTimeInMillis(System.currentTimeMillis());
}

因此它已经可以自动执行您的建议。Date的默认构造函数包含以下内容:

public Date() {
    this(System.currentTimeMillis());
}

因此,实际上确实不需要专门获取系统时间,除非您想在使用它创建Calendar / Date对象之前进行一些数学运算。另外,如果您的目的是大量处理日期计算,那么我确实必须建议使用joda-time来代替Java自己的日历/日期类。


22

如果您要使用日期,则强烈建议您使用http://joda-time.sourceforge.net/的 jodatime 。使用System.currentTimeMillis()该场像一个非常糟糕的主意日期的声音,因为你有很多无用的代码而告终。

日期和日历都严重地令人厌烦,日历绝对是其中表现最差的。

我建议您System.currentTimeMillis()在实际以毫秒为单位进行操作时使用,例如这样

 long start = System.currentTimeMillis();
    .... do something ...
 long elapsed = System.currentTimeMillis() -start;

28
我想,因为你的例子恰好是你应该的事情之一对此置评使用System.currentTimeMillis的()进行; 它不是单调时钟源,因此无法可靠地计算经过的时间。如果在您计时的代码执行期间更改了系统时钟,您将得到怪异的(例如负数)结果。在代替使用System.nanoTime(),它单调如果底层系统支持这样的时钟源(见bugs.java.com/bugdatabase/view_bug.do?bug_id=6458294
REM

System.currentTimeMillis本身不受时区的影响。更改系统时间将以与System.currentTimeMillis相同的方式影响System.nanotime
Viktor

12

我更喜欢使用返回的值System.currentTimeMillis()进行各种计算和只使用Calendar或者Date,如果我需要真正显示由人类阅读的价值。这还将防止您的夏时制错误的99%。:)


12

在我的机器上,我尝试检查它。我的结果:

Calendar.getInstance()。getTime()(* 1000000次)= 402ms
新的Date()。getTime(); (* 1000000次)= 18ms
System.currentTimeMillis()(* 1000000次)= 16ms

不要忘了GC(如果您使用Calendar.getInstance()new Date()


1
怀疑其他进程之间是否有许多线程调用相同线程是否会有任何区别
tgkprog 2013年

7

根据您的应用程序,您可能需要考虑System.nanoTime()改为使用。


为什么,他的问题是关于资源和性能的,nanoTime()使用了更多资源
WolfmanDragon

我之所以提到它,是因为没有其他人建议这样做。张贴者未指定平台。SDN错误6876279建议在某些JDK版本中,currentTimeMillis()和nanoTime()大致相同。张贴者也没有具体说明他们的准确性需求,因为原始名单可能不够。
MykennaC 2010年

4
可能这么晚,问题中的所有示例都对例如几点钟有了绝对的了解。自Unix时代开始以来的1,348,770,313,071毫秒。nanoTime返回的时间是相对的(通常是相对于程序的开始),如果您尝试将其转换为日期,那将是无稽之谈。
沙丘2012年

是的,但是您可以在程序启动时以一些静态代码存储currentTimeilli和nano,然后使用它们作为偏移量,以使用double var = currentTimeStart-nanoTimeStart + nanoTimeNow
tgkprog从Milli

3

我尝试了这个:

        long now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            new Date().getTime();
        }
        long result = System.currentTimeMillis() - now;

        System.out.println("Date(): " + result);

        now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            System.currentTimeMillis();
        }
        result = System.currentTimeMillis() - now;

        System.out.println("currentTimeMillis(): " + result);

结果是:

Date():199

currentTimeMillis():3


4
这是一个微观基准,您应谨慎相信所获得的结果。看看stackoverflow.com/questions/504103/…
Axel

1
该基准测试没有意义,甚至更好,它表明Java操作系统确实很重要。我在一个循环中运行了数十次相同的基准(将“ now”和“ result”的初始化移出了循环),并且每次运行时我都有一些可爱的区别:Date():322至330; currentTimeMillis():319至322。在其他一些运行中,我的Date():312至318;currentTimeMillis():324到335。因此,恕我直言,它们在实际情况下相当等效(也请查看Date的来源)。JFYI,我在Ubuntu上使用Java7。
桑皮萨

0

System.currentTimeMillis() 显然是最快的,因为它只是一个方法调用,不需要垃圾收集器。


14
您的答案没有任何价值,因为它只是先前批准的答案的一部分。您应该尝试不以这种方式回答,尤其是不要认为这是一个已经存在质量问题的非常老的问题。
Nicklas Gnejs Eriksson 2014年

1
其次,无论如何,伊甸园空间中的短期对象都不需要垃圾收集器。
Niels Bech Nielsen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.