指定されたタイムアウトのために現在のスレッドをパークするには、次を使用できます。
LockSupport.parkNanos(long nanos);
また
Thread.sleep(long millis);//internally same as Object.wait(long) i guess.
残念ながら、この 2 つの方法の内部ティックはすべてシステム クロックに基づいています。
待機中にシステム クロックが (ntptime または手動で) 変更された場合、これらのメソッドは期待どおりに動作しません。
たとえば、t0 では、Thread.sleep(dt) のようにこのメソッドを呼び出して、dt 秒スリープします。待機期間中、システムクロックを 20 秒進めると、スレッドは実際には dt+20 秒間スリープします。
次のコードを使用して確認します。
public static void main(String[] args) throws InterruptedException {
long s = System.nanoTime();
int _10sec = 10 * 1000;
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(_10sec));
//or Thread.sleep(_10sec);
long e = System.nanoTime();
long used = e - s;
System.out.println("Used:" + TimeUnit.NANOSECONDS.toMillis(used)); }
「date && sudo date -s 16:10:40」のようなものを使用して、待機中にシステムクロックを数分間進めます。出力から何が起こったのかがわかります。
悲しいことに、私の製品では多くのことがシステム クロックに基づいているため、
ソケット接続を介したハートビート チェッカーのスケジューラ (LockSupport.park を最後に呼び出す) など。
システム クロックがタイムアウトよりも長く設定された場合、スケジューラはタイムアウトと見なしますが、実際にはそうではありません。
誰もが同じ問題に遭遇し、どのように解決しますか?
編集:
私の HA 製品では、重い負荷がシステムをブロックしているときに Watchdog を使用して OS を強制終了します (いわゆる自殺戦略)。望まない自殺を防ぐために犬に餌をやる必要があります,ThreadSupport.parkNanos(xxx) を使用すると予期しない自殺が発生します