java中的精确计时

Jas*_*eng 2 java time

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

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Bas*_*que 6

太长了;博士

\n

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

\n

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

\n

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

\n

Thread.sleep

\n

您可以要求以纳秒的分辨率休眠,但由于当前计算机硬件的限制,您可能无法获得它。请参阅另一种sleep方法,其第二个参数为纳秒。

\n
Thread.sleep( 0L , 300L ) ;  // Ask to sleep 300 nanoseconds.\n
Run Code Online (Sandbox Code Playgroud)\n

的行为Thread.sleep从来都不是确定性可靠的,如下所述。CPU内部调度(如乱序执行、超线程)、JVM的操作系统调度、线程的JVM\xe2\x80\x99s调度以及偶尔的垃圾回收等许多因素都会影响实际的执行时序。因此,除非您转向实时 Java实现,否则您永远不能指望可预测的执行。

\n

System.nanoTime

\n

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

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

Instant

\n

要获取分辨率为纳秒的 UTC 当前时刻,请使用java.time.Instantclass. 在 Java 8 中,当前时刻只能捕获到毫秒,但在 Java 9 及更高版本中,新的实现可以Clock提供更精细的分辨率。我看到macOS Sierra 上的 Oracle JDK 9.0.4 捕获了微秒。

\n
Instant instant = Instant.now() ;  // Capture the current moment in UTC with a resolution of nanoseconds though likely with precision not as fine.\n
Run Code Online (Sandbox Code Playgroud)\n
\n

2018-03-16T01:18:54.898583Z

\n
\n

Duration

\n

我建议通常Instant按原样使用对象。您可以通过isBeforeisAfter、 和equals方法进行比较。要计算经过的时间,请使用Duration.between.

\n
Duration d = Duration.between( instantThen , Instant.now() ) ;  // A span of time not attached to the timeline, with a resolution of nanoseconds.\n
Run Code Online (Sandbox Code Playgroud)\n

避免System.currentTimeMillis\xe2\x80\x8b()

\n

至于System.currentTimeMillis\xe2\x80\x8b(),你可以忘记这个方法。你最好Instant还是使用它。

\n

执行者

\n

至于TimerTimerTask,您应该知道这些类现在已成为遗留类,已被 Java 5 及更高版本中添加的更复杂的Executor框架所取代。请参阅Oracle 教程

\n

实时Java

\n

即使使用执行器,您也无法期望执行时精确的瞬间精度。主机操作系统控制 JVM 的调度,其性能可能会有所不同。在 JVM 中,线程是动态调度的,并且它们的性能可能会有所不同。特别是,垃圾收集可能会影响特定时刻的性能。

\n

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

\n
\n

关于java.time

\n

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

\n

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

\n

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

\n

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

\n

从哪里获取 java.time 类?

\n\n

ThreeTen -Extra项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如Interval、、、等等。YearWeekYearQuarter

\n