質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1457閲覧

JavaのSystem.nanoTimeよりSystem.currentTimeMillisを使用すべき理由

hirai

総合スコア13

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

3グッド

1クリップ

投稿2019/02/09 17:34

初学者のためJavaでゲームループを作ろうと思っております。

ただ、8年ほど前の個人ブログの記事で「System.nanoTimeは外部から操作されやすいので使用を推奨しない」という言及を見つけました。
(その方に直接聞けばいいのでしょうが、もうブログは更新を終えて何年も経っているようです)

殆どの記事は「正確な時間の取得のためにはnanoTimeを使用すべき」と書いてあり、セキュリティ関係の実装にもnanoTimeが使用されているのを見つけたため、
「nanoTimeよりcurrentTimeMillisをすべき理由」がいまいちよくわかりません。
nanoTimeのdeclarationに「うっかりするとオーバーフローを起こすから気をつけてね(意訳)」的な事が書いてあるのでその意味でしょうか?
わりと最近の記事でもnanotimeではなくcurrentTimeMillisを起用しているゲームループを見かけ、あえてnanotimeのような高い分解能のメソッドを使う理由もないのかもしれないとは思いましたが、
JavaFXのAnimationTimerではhandleがナノ秒を引数として持っているのを考えるとやはりnanoTimeで問題ないのでは、という気がしています。

掴みどころのない質問で申し訳ありません、よろしくおねがいします。

matobaa, yukkuri, KSwordOfHaste👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

https://stackoverflow.com/questions/510462/is-system-nanotime-completely-useless

このあたりの話が関係しているのかも知れません。昔のnanoTimeの実装ではプロセッサーごとのクロックが用いられていたりしてある時点の時刻が後の時刻より大きな値になることがあるとかなんとか・・・

Tom氏の回答やそこからリンクされているleventov氏の回答の回答などが興味深い内容になっています。

公式ドキュメントではnanoTimeの動作をはっきり保証しているものの「OpenJDKには過去いろいろバグが起きたのでこれから起きても不思議じゃない」というコメントが不気味です...

それはともかく、そうしたバグの可能性なども加味した上で

java

1class MyClock { 2 long older = System.nanoTime(); 3 4 long elapsed() { 5 long newer = System.nanoTime(); 6 long elapsed = newer - older; 7 older = newer; 8 if (elapsed < 0) { 9 elapsed = 0; 10 } 11 return elapsed; 12 } 13}

などとやっておけばまずはよかろう的なことが書いてありますね。

ちなみにSystem.currentTimeMillis()は時刻間隔の測定には適さないと書いてありますね。ホストの時刻補正(NTPとかで自動的に補正されることでしょうか?)の影響を被るからだと書いてあります。確かに!今まであまり気にしてませんでしたがいわれてみればおっしゃるとおりという感じです。

自分なりの意見は

オーバーフローや万一のことを考えた配慮をちょっとやっておけばnanoTimeを使うことの方が妥当

です。

プログラミングの練習で作るゲーム的なものでしたらnanoTimeでもcurrentTimeMillisでもそうまで気にする必要はない気もしますが、前述の時刻補正の影響云々を考えるとnanoTimeの方が妥当に思えました。

投稿2019/02/09 19:27

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirai

2019/02/10 10:49

丁寧なご回答をありがとうございました。 早速ゲームループをNanoTime準拠(追い越し事故防止関数付き)に変更してみました。 割り算の代わりにcurrentTimeMillisをビットシフトするコードだったのでNanoTimeだときれいにビットシフト出来ない問題が出てしまいましたが、割り算とビットシフトにさほど大きな速度計算差がないということがわかり思わぬ副産物がありました。 大変助かりました、ありがとうございました。
KSwordOfHaste

2019/02/10 10:59

ご質問がきっかけで自分も色々参考になりました。
guest

0

以下が関連しているでしょうか。

Stack overflow - Is System.nanoTime() completely useless?
Beware of System.nanoTime() in Java

要は、System.nanoTimeはマルチコア以上のCPUではそれぞれのCPUでの経過時間を返すのに対しSystem.currentTimeMillisは単に現在の時間をミリ秒で返します。

「正確な時間」の「正確」が、どの部分の正確さを指すかでどちらを使うべきかが変わってきます。簡単に考えると、プログラム全体での経過時間を計るのであればSystem.currentTimeMillisであろうし、CPUへの割り振り具合までよく考えてスレッド単位で制御するようなケースでは、System.nanoTimeを利用するのが適切なケースもありそうです。

「System.nanoTimeは外部から操作されやすいので使用を推奨しない」

の真意は定かではありませんが、CPU単位での経過時間ならばCPUの稼動範囲を外部から操作することで変えられそうで、その意味かもしれません。対してSystem.currentTimeMillisは単なる実時間での経過時間なので、CPUの動作状態によって変わることはないことになります。

投稿2019/02/09 18:44

編集2019/02/09 18:50
dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirai

2019/02/10 10:56

ご回答ありがとうございました。NanoTimeは危険なのにcurrentTimeMillisなら平気という理屈がイマイチよくわからず、暗号関連のコードにもNanoTimeが起用されているのを見かけたので、NanoTimeを使っていこうかと思います(JavaFXのAnimationTimerと単位を揃えた方が具合がよさそうという判断もあります)。 お調べくださりありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問