java中的准确计时 [英] Accurate timing in java

查看:31
本文介绍了java中的准确计时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 Java 中实现准确计时?我知道 Thread.sleep() 不准确并导致 InterruptedExceptions.我正在尝试制作一个物理模拟器,我想要准确的代码.到目前为止,这是我的代码:

public class FreeFall() {公共静态无效主(字符串 [] args){双高度 = Double.parseDouble(args[0]);双 xi = 高度;整数计数器 = 0;而(真){高度 = xi + 9.8/* 计数器 * 计数器;System.out.println(高度);计数器++;线程睡眠(1000);}}}

解决方案

tl;dr

Java 的传统实现不是实时系统.所以你不能指望确定性的性能.

如果您坚持确定性时间,请寻找 实时 Java 的实现.

类似问题:Java - thread.sleep 的替代方案

Thread.sleep

您可以要求以纳秒分辨率进行睡眠,但由于当前计算机硬件的限制,您可能无法获得它.请参阅其他sleep 方法 以纳秒为单位采用第二个参数.

Thread.sleep( 0L , 300L ) ;//要求睡眠 300 纳秒.

Thread.sleep 的行为永远不是确定性可靠的,如下所述.CPU内部调度(如乱序执行、超线程)、JVM的OS调度、JVM对线程的调度、偶尔的垃圾回收等诸多因素都会影响实际的执行时间.因此,除非您转向 实时 Java 实现,否则您永远不能指望可预测的执行.

System.nanoTime

要跟踪经过的时间,请调用 System.nanoTime.这具有纳秒的分辨率,但精度不太可能.截至 2018 年,传统的计算机硬件时钟只能精确到微秒左右的范围,而不是纳秒.这对于诸如微基准测试之类的事情很有用(提示:JMH).System.nanoTime 与告诉当前日期时间无关.返回的数字是某个未记录的原始时刻的计数(根据我的经验,自 JVM 启动以来,但不能保证).连续运行几十年,64 位数字可能会溢出.

long start = System.nanoTime() ;//只是一些逐渐增加的纳秒数.不是当前的日期时间.长停 = System.nanoTime() ;时间长了=(停止-开始);//以纳秒级的分辨率计算经过的时间(尽管不太可能精确到微秒级以上).

即时

要以 纳秒 的分辨率获取 UTC 中的当前时刻,请使用 java.time.Instant 班级.在 Java 8 中,当前时刻只能捕获到毫秒,但在 Java 9 和更高版本中,Clock<的全新实现/code> 可能会提供更精细的分辨率.我看到 微秒 在 macOS Sierra 上的 Oracle JDK 9.0.4 中捕获.

Instant Instant = Instant.now() ;//以纳秒的分辨率捕获 UTC 中的当前时刻,尽管精度可能不那么好.

<块引用>

2018-03-16T01:18:54.898583Z

持续时间

我建议一般使用 Instant 对象原样.您可以通过 isBeforeisAfterequals 方法.要计算经过的时间,请使用 Duration.between.

Duration d = Duration.between( instantThen , Instant.now() ) ;//不附加到时间线的时间跨度,分辨率为纳秒.

避免System.currentTimeMillis ()

至于System.currentTimeMillis (),你可以忘记这个方法.您最好改用 Instant.

执行者

至于定时器TimerTask,您应该知道这些类现在是遗留的,被 Java 5 及更高版本中添加的更复杂的 Executor 框架所取代.请参阅Oracle 教程.

实时 Java

即使使用 Executors,您也不能期望在执行中达到精确的分秒精度.主机操作系统控制 JVM 的调度,其性能可能会有所不同.在 JVM 中,线程是动态调度的,它们的性能可能会有所不同.特别是,垃圾收集可能会在特定时刻影响性能.

如果您想要确定性的执行时间,您需要获得 实时 Java.Java 的传统实现(例如 Oracle JDK 和 OpenJDK)肯定不是实时系统.

<小时>

关于java.time

java.time 框架内置于 Java 8 及更高版本中.这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date, Calendar, &SimpleDateFormat.

Joda-Time 项目,现在在 维护模式,建议迁移到 java.time 类.

要了解更多信息,请参阅 Oracle 教程.并在 Stack Overflow 上搜索许多示例和解释.规范是 JSR 310.

您可以直接与您的数据库交换 java.time 对象.使用符合 JDBC 驱动程序/jeps/170" rel="nofollow noreferrer">JDBC 4.2 或更高版本.不需要字符串,不需要 java.sql.* 类.

从哪里获取 java.time 类?

ThreeTen-Extra 项目扩展了 java.time与额外的课程.该项目是未来可能添加到 java.time 的试验场.您可能会在这里找到一些有用的类,例如 间隔YearWeek, YearQuarter更多.

How can I achieve accurate timing in Java? I know Thread.sleep() is inaccurate and leads to InterruptedExceptions. I'm trying to make a physics simulator and I want to have accurate code. Here is my code so far:

public class FreeFall() {
    public static void main(String[] args) {
        double height = Double.parseDouble(args[0]);
        double xi = height;
        int counter = 0;
        while (true) {
            height = xi + 9.8 / * counter * counter;
            System.out.println(height);
            counter++;
            Thread.sleep(1000);
        }
    }
}

解决方案

tl;dr

Conventional implementations of Java are not real-time systems. So you cannot count on deterministic performance.

If you insist on deterministic timing, seek out an implementation of real-time Java.

Similar Question: Java - alternative to thread.sleep

Thread.sleep

You can ask for sleeping with a resolution of nanoseconds, but you may not get it due to limitations of current computer hardware. See the other sleep method taking a second argument for nanoseconds.

Thread.sleep( 0L , 300L ) ;  // Ask to sleep 300 nanoseconds.

The behavior of Thread.sleep is never deterministically reliable, as discussed below. Many factors such as internal CPU scheduling (such as out-of-order execution and hyper-threading), OS scheduling of the JVM, the JVM’s scheduling of threads, and occasional garbage collection all impact the actual execution timing. So you can never count on predictable execution unless you move to a real-time Java implementation.

System.nanoTime

To track elapsed time, call System.nanoTime. This has a resolution of nanoseconds, but not likely precision. As of 2018, conventional computer hardware clocks are only accurate to a range of around microseconds, not nanoseconds. This is good for things such a micro-benchmarking (tip: JMH). The System.nanoTime has nothing to do with telling the current date-time. The number returned is a count from some undocumented origin moment (in my experience, since the JVM launched, but not guaranteed). The 64-bit number may overrun in a few decades of continual running.

long start = System.nanoTime() ; // Just some progressively incrementing number of nanoseconds. NOT the current date-time.
long stop = System.nanoTime() ;
long elapsed = ( stop - start ) ;  // Calculate elapsed time in a resolution as fine as nanoseconds (though not likely precise beyond microseconds).

Instant

To get the current moment in UTC with a resolution of nanoseconds, use java.time.Instant class. In Java 8, the current moment could captured only to milliseconds, but in Java 9 and later a fresh implementation of Clock may deliver finer resolution. I am seeing microseconds captured in Oracle JDK 9.0.4 on macOS Sierra.

Instant instant = Instant.now() ;  // Capture the current moment in UTC with a resolution of nanoseconds though likely with precision not as fine.

2018-03-16T01:18:54.898583Z

Duration

I suggest generally using the Instant objects as-is. You can compare via isBefore, isAfter, and equals methods. To calculate elapsed time, use Duration.between.

Duration d = Duration.between( instantThen , Instant.now() ) ;  // A span of time not attached to the timeline, with a resolution of nanoseconds.

Avoid System.currentTimeMillis​()

As for System.currentTimeMillis​(), you can forget about this method. You are better off using Instant instead.

Executor

As for Timer and TimerTask, you should know that those classes are now legacy, supplanted by the more sophisticated Executor framework added to Java 5 and later. See the Oracle Tutorial.

Real-time Java

Even with Executors, you cannot expect exact split-second accuracy in execution. The host OS controls scheduling the JVM, and its performance may vary. Within the JVM, threads are scheduled dynamically, and their performance may vary. In particular, garbage collection may impact performance at particular moments.

If you want deterministic timing of execution, you need to obtain an implementation of real-time Java. The conventional implementations of Java such as the Oracle JDK and OpenJDK are most certainly not real-time systems.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

这篇关于java中的准确计时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆