1

指定されたタイムアウトのために現在のスレッドをパークするには、次を使用できます。

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) を使用すると予期しない自殺が発生します

4

2 に答える 2

1

私がすることは、毎秒、5秒、または分など、定期的にスリープを解除することです。調整された時間が必要な場合は currentTimeMillis() をチェックでき、単調に増加する時間が必要な場合は nanoTime() をチェックできます。

于 2013-04-11T07:19:29.267 に答える
0

最後に、Linux で JNI を使用してこの問題を解決しました。実際、Java スコープには抜け道がありません。</p>

#include <jni.h>
#include <unistd.h>
#include <LinuxSleeper.h>


JNIEXPORT jint JNICALL Java_com_my_pkg_name_sleep_LinuxSleeper_sleep0
  (JNIEnv *env, jobject thisObj, jint secs){
    if( secs >= 0 ){
        return sleep(secs);
    }else{
        return 0;
    }
}

Java クラスは次のようになります。

public class LinuxSleeper extends CommonSleeper implements Sleeper {

    static {
        NativeUtils.loadLibrary("LinuxSleeper");
    }
@Override
    public int sleep(int seconds) {
     ///....
    }
    private native int sleep0(int seconds);
    }
于 2014-07-08T03:05:45.537 に答える