【问题标题】:System.currentTimeMillis() vs. new Date() vs. Calendar.getInstance().getTime()System.currentTimeMillis() vs. new Date() vs. Calendar.getInstance().getTime()
【发布时间】:2010-09-26 22:54:47
【问题描述】:

在 Java 中,使用对性能和资源的影响是什么

System.currentTimeMillis() 

对比

new Date() 

对比

Calendar.getInstance().getTime()

据我了解,System.currentTimeMillis() 是最有效的。但是,在大多数应用程序中,需要将 long 值转换为 Date 或一些类似的对象才能执行对人类有意义的任何事情。

【问题讨论】:

    标签: java performance date time calendar


    【解决方案1】:

    System.currentTimeMillis() 显然是最高效的,因为它甚至不创建对象,但new Date() 实际上只是一个大约很长的薄包装器,所以它也不甘落后。另一方面,Calendar 相对较慢且非常复杂,因为它必须处理日期和时间(闰年、夏令时、时区等)所固有的相当复杂和所有奇怪的问题。

    通常最好只处理应用程序中的长时间戳或Date 对象,并且仅在您实际需要执行日期/时间计算或格式化日期以向用户显示它们时才使用Calendar .如果你必须做很多这样的事情,使用Joda Time 可能是个好主意,因为它的界面更简洁,性能更好。

    【讨论】:

    • timestamp和currentMillis有什么区别?
    • @pinkpanther:“timestamp”通常用于描述一个整数/长整数,当解释为“纪元开始”以来的秒数或毫秒时,它描述了一个时间点。换句话说,currentTimeMillis() 返回一个时间戳。
    【解决方案2】:

    查看 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());
    }
    

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

    【讨论】:

      【解决方案3】:

      如果您使用日期,那么我强烈建议您使用 jodatime,http://joda-time.sourceforge.net/。将System.currentTimeMillis() 用于日期的字段听起来是个非常糟糕的主意,因为你最终会得到很多无用的代码。

      日期和日历都非常糟糕,日历绝对是其中表现最差的。

      我建议您在实际使用毫秒操作时使用System.currentTimeMillis(),例如像这样

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

      【讨论】:

      • 我想对此发表评论,因为您的示例正是您应该使用 System.currentTimeMillis() 的事情之一;它不是一个单调的时钟源,所以你不能用它可靠地计算经过的时间。如果在您正在计时的代码正在执行时更改系统时钟,您将得到奇怪的(例如否定的)结果。而是使用 System.nanoTime(),它单调如果底层系统支持这样的时钟源(参见bugs.java.com/bugdatabase/view_bug.do?bug_id=6458294
      • System.currentTimeMillis 本身不受时区影响。更改系统时间会像 System.currentTimeMillis 一样影响 System.nanotime
      • @Viktor 不正确,nanoTime() 是一个始终递增的计数器,它永远不会返回小于上次在此 JVM 实例中调用的值。 currentTimeMillis() 可以返回小于上次调用时间的值,因为系统时间正在更改,例如NTP 时钟同步。
      【解决方案4】:

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

      Calendar.getInstance().getTime() (*1000000 次) = 402ms 新日期().getTime(); (*1000000 次) = 18ms System.currentTimeMillis() (*1000000 次) = 16ms

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

      【讨论】:

      • 想知道如果许多线程在其他处理之间调用相同的会有什么不同
      【解决方案5】:

      我更喜欢将System.currentTimeMillis() 返回的值用于各种计算,并且仅在我需要真正显示人类读取的值时才使用CalendarDate。这也将防止 99% 的夏令时错误。 :)

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 为什么,他的问题是关于资源和性能,nanoTime() 使用更多资源
        • 我提到它是因为这是一个没有其他人建议的选项。海报没有指定平台。 SDN 错误 6876279 表明 currentTimeMillis() 和 nanoTime() 在某些 JDK 版本中的使用大致相同。发布者也没有具体说明他们的准确性需求,原始列表可能不足以满足这些需求。
        • 这可能很晚,但问题中的所有示例都有一个绝对的时间概念,例如。自 Unix 纪元开始以来的 1,348,770,313,071 毫秒。 nanoTime 返回的时间是相对的(通常是程序开始的时间),如果你试图把它变成一个日期,那将是无稽之谈。
        • 是的,但是您可以在程序启动时将 currentTimeilli 和 nano 存储在一些静态代码中,然后使用它们作为偏移量,使用 double var = currentTimeStart - nanoTimeStart + nanoTimeNow 从 milli 获取准确的 nano
        【解决方案7】:

        我试过了:

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

        结果是:

        日期():199

        currentTimeMillis(): 3

        【讨论】:

        • 这是一个微基准测试,你应该小心相信你得到的结果。看看stackoverflow.com/questions/504103/…
        • 这个基准没有意义,或者更好,它表明Java下的操作系统确实很重要。我在循环中运行了十多次相同的基准测试(将“现在”和“结果”的初始化移出循环),每次运行我都有可爱的差异: Date() : 322 to 330; currentTimeMillis():319 到 322。在其他一些运行中,我有 Date():312 到 318; currentTimeMillis():324 到 335。所以,恕我直言,在实际情况下它们是相当的(也查看日期的来源)。 JFYI,我在 Ubuntu 上使用过 Java7。
        【解决方案8】:

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

        【讨论】:

        • 您的答案没有任何价值,因为它只是之前批准的答案的一个子集。您应该尽量不要以这种方式回答,尤其不要考虑到这是一个非常古老的问题,并且已经存在高质量的答案。
        • 其次,Eden 空间中的短期对象无论如何都不需要垃圾收集器。
        猜你喜欢
        • 2019-03-12
        • 2016-05-19
        • 1970-01-01
        • 2020-08-23
        • 2020-03-12
        • 2020-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多