398

精度対 精度

私が知りたいのは、ゲーム内のオブジェクトの位置を更新するときにSystem.currentTimeMillis()System.nanoTime( )のどちらを使用する必要があるかということです。彼らの動きの変化は、最後の呼び出しからの経過時間に正比例します。可能な限り正確にしたいと思います。

異なるオペレーティングシステム間でいくつかの深刻な時間解像度の問題があることを読みました(つまり、Mac / Linuxの解像度はほぼ1ミリ秒ですが、Windowsの解像度は50ミリ秒ですか??)。私は主にWindowsでアプリを実行していますが、50ミリ秒の解像度はかなり不正確なようです。

私がリストした2つよりも良いオプションはありますか?

何か提案/コメントはありますか?

4

10 に答える 10

336

経過時間の非常に正確な測定値を探しているだけの場合は、 を使用してSystem.nanoTime()ください。System.currentTimeMillis()エポックからの最も正確な経過時間をミリ秒単位で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()も参照してください。

于 2008-12-09T02:06:01.230 に答える
110

誰もこれについて言及していないので…</p>

異なるJVM間の呼び出しの結果を比較することは安全ではありませんSystem.nanoTime()。各JVMには、独立した「起点」時間があります。

System.currentTimeMillis()システムの実時間に関連付けられているため、JVM間で(ほぼ)同じ値を返します。

ストップウォッチなど、2つのイベント間で経過した時間を計算する場合は、nanoTime();を使用します。システムの壁掛け時計の変更は、currentTimeMillis()このユースケースでは正しくありません。

于 2012-02-16T16:03:33.330 に答える
59

Arkadiyによる更新: Windows 7 での Oracle Java 8 のより正しい動作を観察しましたSystem.currentTimeMillis()。時間は 1 ミリ秒の精度で返されました。OpenJDK のソース コードは変更されていないため、何が原因で動作が改善されるのかわかりません。


Sun の David Holmes が数年前にブログ記事を投稿しました。この記事では、Java タイミング API (特にSystem.currentTimeMillis()System.nanoTime())、いつ使用する必要があるか、内部でどのように機能するかについて詳しく説明しています。

Hotspot VM の内部: クロック、タイマー、スケジュール イベント - パート I - Windows

Windows 上の Java が時間指定待機パラメーターを持つ API に使用するタイマーの非常に興味深い側面の 1 つは、他の API 呼び出しが行われた可能性に応じて (特定のプロセスだけでなく) システム全体でタイマーの解決が変わる可能性があることです。 . Thread.sleep()彼は、使用するとこの解像度が変化する例を示しています。

于 2008-12-09T06:06:04.880 に答える
11

System.nanoTime()古い JVM ではサポートされていません。それが懸念される場合は、そのままにしてくださいcurrentTimeMillis

精度に関しては、ほぼ正しいです。一部の Windows マシンでcurrentTimeMillis()は、約 10 ミリ秒 (50 ミリ秒ではありません) の解像度があります。理由はわかりませんが、一部の Windows マシンは Linux マシンと同じくらい正確です。

私は過去にGAGETimerを使ったことがありますが、中程度の成功を収めています。

于 2008-12-09T02:06:21.557 に答える
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)); }
    }
于 2008-12-09T02:24:09.150 に答える
1

私はnanotimeで良い経験をしました。JNI ライブラリを使用して、ウォールクロック時間を 2 つの倍長 (エポックからの秒数とその秒内のナノ秒) として提供します。Windows と Linux の両方用にプリコンパイルされた JNI 部分で利用できます。

于 2011-04-21T11:01:25.817 に答える
-3

ここでの 1 つのことは、nanoTime メソッドの不一致です。同じ入力に対して非常に一貫した値が得られません。currentTimeMillis は、パフォーマンスと一貫性の点ではるかに優れています。また、nanoTime ほど正確ではありませんが、誤差の範囲が小さくなっています。 、したがって、その値の精度が向上します。したがって、 currentTimeMillis を使用することをお勧めします

于 2012-04-24T04:52:10.777 に答える