👋
Thread.sleep の待機時間
Windows 上の Java (Kotlin) でのスリープが、想定と異なる挙動でした。
ミリ秒を指定するけど、待機時間が指定に満たないような場合がある。
val t1 = System.nanoTime()
Thread.sleep(100)
val t2 = System.nanoTime()
val dt = t2 - t1
check(dt >= 100_000_000 /* 100 ms */) { "${dt} ns" }
// ==> 99922800 ns
スリープ系の呼び出しは最短待機時間の指定だと思っていたし、
モノトニックタイマーの精度は少なくともマイクロ秒はあると思うので、ちょっと意外。
JVM の問題かもしれないけど、スレッドの待機はそのまま OS の API 呼び出しになっていそうだし。
System.nanoTime() の精度が思ったよりも悪いのだろうか。
subject to the precision and accuracy of system timers and schedulers
dwMilliseconds がシステム クロックの解像度より小さい場合、スレッドは、指定された時間未満でスリープ状態になる可能性があります。 dwMilliseconds が 1 ティックより大きく、2 未満の場合、待機は 1 ティックから 2 ティックまでの任意の場所にできます。
なるほど
システムタイマー分解能(クロック割り込み間隔):15.625000 ms
マルチメディアタイマー分解能:1 ms
高分解能カウンター分解能:0.000279 ms
これは19年前の情報だけど、分解能がミリ秒単位の整数でない可能性があるのか
昔、自分で調べたときは 50 ms くらいで、分解能を上げると 1 ms とかにできた記憶がある
まとめると、確実にある時間以上を待機したい場合は、OSのティックを調べた上で加算しておかないといけないのか、意外と面倒な仕様だった、、、
Discussion