簡體   English   中英

Java中的准確計時

[英]Accurate timing in java

如何在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);
        }
    }
}

您可能想利用時間戳,利用System.currentTimeMillis() ,它會給您自1970年1月1日起經過的毫秒數。

當對象開始掉落時,請加上時間戳記。 然后,在循環中,您可以使用代表當前時間的時間戳記。 currentTime減去startTime ,您將獲得准確的毫秒數。 例如,通過此計算,您可以計算出在給定速度下該對象在該時間段內應下落的距離。

這種方法的好處在於,無論運行在快速還是慢速的處理器上都沒有關系,因為時間戳反映了實際的時間流逝與循環迭代次數之間的關系。

TL;博士

Java的常規實現不是實時系統。 因此, 您不能指望確定性性能

如果您堅持確定性時序,請尋求實時Java的實現

相似的問題: Java-替代thread.sleep

Thread.sleep

您可以要求睡眠時間為納秒級,但是由於當前計算機硬件的限制,您可能無法入睡。 請參閱另一個sleep方法 ,將第二個參數設為納秒。

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

如下所述, Thread.sleep的行為永遠不會確定可靠。 內部CPU調度(例如亂序執行和超線程),JVM的OS調度,JVM的線程調度以及偶爾的垃圾回收等許多因素都會影響實際的執行時間。 因此,除非移至實時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.
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

要獲得UTC的當前時刻,分辨率為納秒 ,使用java.time.Instant類。 在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.

2018-03-16T01:18:54.898583Z

Duration

我建議通常按原樣使用Instant對象。 您可以通過isBeforeisAfterequals方法進行比較。 要計算經過的時間,請使用Duration.between

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

避免使用System.currentTimeMillis​()

至於System.currentTimeMillis​() ,您可以忘記此方法。 您最好改用Instant

執行者

至於TimerTimerTask ,您應該知道這些類現在是遺留的,被Java 5和更高版本中添加的更復雜的Executor框架所取代。 請參閱《 Oracle教程》

實時Java

即使使用執行器,您也無法期望執行過程中具有精確的瞬間精度。 主機OS控制調度JVM,其性能可能會有所不同。 在JVM中,線程是動態調度的,它們的性能可能會有所不同。 特別是,垃圾收集可能會在特定時刻影響性能。

如果您需要確定的執行時間,則需要獲取實時Java的實現 當然,諸如Oracle JDK和OpenJDK之類的Java常規實現絕非 實時系統


關於java.time

java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.DateCalendarSimpleDateFormat

現在處於維護模式Joda-Time項目建議遷移到java.time類。

要了解更多信息,請參見Oracle教程 並在Stack Overflow中搜索許多示例和說明。 規格為JSR 310

您可以直接與數據庫交換java.time對象。 使用與JDBC 4.2或更高版本兼容的JDBC驅動程序 不需要字符串,不需要java.sql.*類。

在哪里獲取java.time類?

  • Java SE 8Java SE 9和更高版本
    • 內置。
    • 標准Java API的一部分,具有捆綁的實現。
    • Java 9添加了一些次要功能和修復。
  • Java SE 6Java SE 7
    • java.time的許多功能在ThreeTen- Backport中都被反向移植到Java 6和7。
  • Android的
    • 更高版本的Android捆綁了java.time類的實現。
    • 對於早期的Android(<26), ThreeTenABP項目改編了ThreeTen-Backport (如上所述)。 請參閱如何使用ThreeTenABP…

ThreeTen-Extra項目使用其他類擴展了java.time。 該項目為將來可能在java.time中添加內容提供了一個試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

對於Java 8及更高版本-您可以使用java.time庫,它具有日期時間類

對於日期-

  //To create a new date
LocalDate ld =  LocalDate.Of(2018,March,26);
   //To print current date
LocalDate.now();

對於時間-

 //To create a new time
LocalTime lt = LocalTime.Of(11,22);
   //To print current time
Local time.now();

對於日期和時間-

   //To create a new date time
LocalDateTime ldt = LocalDateTime.Of(2018,March,26,11,22);
   //To print current date time
LocalDateTime.now();

注意:請注意以下事項-這些類僅在Java 8及更高版本中可用。 -這些類具有私有構造函數,因此您無法實例化它們-Of是靜態方法,因此使用類名進行調用-這些類是不可變的,因此您需要創建的任何更新都將保存到新對象中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM