如何在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)
Java 的传统实现不是实时系统。所以你不能指望确定性的性能。
\n如果您坚持确定性计时,请寻找实时 Java的实现。
\n\nThread.sleep您可以要求以纳秒的分辨率休眠,但由于当前计算机硬件的限制,您可能无法获得它。请参阅另一种sleep方法,其第二个参数为纳秒。
Thread.sleep( 0L , 300L ) ; // Ask to sleep 300 nanoseconds.\nRun Code Online (Sandbox Code Playgroud)\n的行为Thread.sleep从来都不是确定性可靠的,如下所述。CPU内部调度(如乱序执行、超线程)、JVM的操作系统调度、线程的JVM\xe2\x80\x99s调度以及偶尔的垃圾回收等许多因素都会影响实际的执行时序。因此,除非您转向实时 Java实现,否则您永远不能指望可预测的执行。
System.nanoTime要跟踪经过的时间,请致电System.nanoTime。它的分辨率为纳秒,但精度不太高。截至 2018 年,传统的计算机硬件时钟只能精确到微秒左右,而不是纳秒。这对于微基准测试等事情很有用(提示:JMH)。System.nanoTime与告知当前日期时间无关。返回的数字是来自某个未记录的原始时刻的计数(根据我的经验,自 JVM 启动以来,但不能保证)。64位数字在连续运行几十年后可能会溢出。
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).\nRun Code Online (Sandbox Code Playgroud)\nInstant要获取分辨率为纳秒的 UTC 当前时刻,请使用java.time.Instantclass. 在 Java 8 中,当前时刻只能捕获到毫秒,但在 Java 9 及更高版本中,新的实现可以Clock提供更精细的分辨率。我看到macOS Sierra 上的 Oracle JDK 9.0.4 捕获了微秒。
Instant instant = Instant.now() ; // Capture the current moment in UTC with a resolution of nanoseconds though likely with precision not as fine.\nRun Code Online (Sandbox Code Playgroud)\n\n\n2018-03-16T01:18:54.898583Z
\n
Duration我建议通常Instant按原样使用对象。您可以通过isBefore、isAfter、 和equals方法进行比较。要计算经过的时间,请使用Duration.between.
Duration d = Duration.between( instantThen , Instant.now() ) ; // A span of time not attached to the timeline, with a resolution of nanoseconds.\nRun Code Online (Sandbox Code Playgroud)\nSystem.currentTimeMillis\xe2\x80\x8b()至于System.currentTimeMillis\xe2\x80\x8b(),你可以忘记这个方法。你最好Instant还是使用它。
至于Timer和TimerTask,您应该知道这些类现在已成为遗留类,已被 Java 5 及更高版本中添加的更复杂的Executor框架所取代。请参阅Oracle 教程。
即使使用执行器,您也无法期望执行时精确的瞬间精度。主机操作系统控制 JVM 的调度,其性能可能会有所不同。在 JVM 中,线程是动态调度的,并且它们的性能可能会有所不同。特别是,垃圾收集可能会影响特定时刻的性能。
\n如果您想要确定的执行时间,您需要获取实时 Java的实现。Java 的传统实现(例如 Oracle JDK 和 OpenJDK)肯定不是 实时系统。
\njava.time框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat。
Joda -Time项目现在处于维护模式,建议迁移到java.time类。
\n要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
\n您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
从哪里获取 java.time 类?
\nThreeTen -Extra项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如Interval、、、等等。YearWeekYearQuarter
| 归档时间: |
|
| 查看次数: |
3643 次 |
| 最近记录: |