System.currentTimeMillis和System.nanoTime

精度與 精確

我想知道的是在更新對象在遊戲中的位置時應該使用System.currentTimeMillis()仍是System.nanoTime() ? 他們的運動變化與自上次通話以來通過的時間成正比,我想盡量地精確。 性能

我瞭解到,不一樣的操做系統之間存在一些嚴重的時間分辨率問題(即Mac / Linux的分辨率幾乎爲1毫秒,而Windows的分辨率爲50毫秒?)。 我主要是在Windows上運行個人應用,而50ms的分辨率彷佛很是不許確。 spa

是否有比我列出的兩個更好的選擇? 操作系統

有什麼建議/意見嗎? code


#1樓

這裏的一件事是nanoTime方法的不一致。對於相同的輸入,它不會給出很是一致的值。currentTimeMillis在性能和一致性方面要好得多,而且儘管不如nanoTime精確,但偏差範圍較小,所以其值的準確性更高。 所以,我建議您使用currentTimeMillis 對象


#2樓

就像其餘人所說的,currentTimeMillis是時鐘時間,因爲夏時制,用戶更改時間設置,leap秒和互聯網時間同步而改變。 若是您的應用依賴於單調增長的通過時間值,則您可能更喜歡nanoTime。 遊戲

您可能會認爲玩家不會在遊戲過程當中擺弄時間設置,也許您是對的。 可是,請不要低估因爲Internet時間同步或遠程桌面用戶形成的中斷。 nanoTime API不受這種破壞的影響。 開發

若是要使用時鐘時間,但要避免因爲Internet時間同步而致使中斷,則能夠考慮使用NTP客戶端(例如Meinberg),該客戶端能夠將時鐘速率「調整」爲零,而不只僅是按期重置時鐘。 文檔

我是根據我的經驗講的。 在我開發的天氣應用程序中,我獲得了隨機出現的風速峯值。 我花了一段時間才意識到典型的PC上的時鐘時間行爲干擾了個人時基。 當我開始使用nanoTime時,我全部的問題都消失了。 一致性(單調性)對個人應用程序比原始精度或絕對精度更重要。 get


#3樓

若是你只是在尋找的通過時間很是精確的測量,使用System.nanoTime() System.currentTimeMillis()將爲您提供自該紀元以來最精確的通過時間(以毫秒爲單位System.nanoTime() ,可是System.nanoTime()爲您提供相對於某個任意點的納秒級精確時間。 同步

從Java文檔中:

public static long nanoTime()

返回最精確的可用系統計時器的當前值(以納秒爲單位)。

此方法只能用於測量通過時間,而且與系統或掛鐘時間的任何其餘概念無關。 返回的值表示自某個固定但任意的原始時間以來的納秒(也許是未來的時間,所以值可能爲負)。 此方法提供納秒精度,但不必定提供納秒精度。 不能保證值更改的頻率。 因爲數值溢出,跨越大約292年(2 63納秒)的連續呼叫中的差別將沒法準確計算通過的時間。

例如,要測量某些代碼執行所需的時間:

long startTime = System.nanoTime();    
// ... the code being measured ...    
long estimatedTime = System.nanoTime() - startTime;

另請參閱: JavaDoc System.nanoTime()JavaDoc System.currentTimeMillis()瞭解更多信息。


#4樓

較早的JVM不支持System.nanoTime() 。 若是這是一個問題,請堅持使用currentTimeMillis

關於準確性,您幾乎是正確的。 在某些Windows計算機上, currentTimeMillis()的分辨率約爲10毫秒(而非50毫秒)。 我不肯定爲何,可是某些Windows機器和Linux機器同樣準確。

我過去使用GAGETimer取得了必定的成功。


#5樓

是的,若是須要這種精度,請使用System.nanoTime() ,可是請注意,您那時須要Java 5+ JVM。

在個人XP系統上,使用如下代碼,我看到系統時間至少報告爲 100微秒 278 納秒

private void test() {
    System.out.println("currentTimeMillis: "+System.currentTimeMillis());
    System.out.println("nanoTime         : "+System.nanoTime());
    System.out.println();

    testNano(false);                                                            // to sync with currentTimeMillis() timer tick
    for(int xa=0; xa<10; xa++) {
        testNano(true);
        }
    }

private void testNano(boolean shw) {
    long strMS=System.currentTimeMillis();
    long strNS=System.nanoTime();
    long curMS;
    while((curMS=System.currentTimeMillis()) == strMS) {
        if(shw) { System.out.println("Nano: "+(System.nanoTime()-strNS)); }
        }
    if(shw) { System.out.println("Nano: "+(System.nanoTime()-strNS)+", Milli: "+(curMS-strMS)); }
    }
相關文章
相關標籤/搜索