1

要使当前线程停在指定的超时时间,我可以使用:

LockSupport.parkNanos(long nanos);

或者

Thread.sleep(long millis);//internally same as Object.wait(long) i guess.

不幸的是,这两种方法的内部滴答都是基于系统时钟的。

如果在等待期间更改系统时钟(通过 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)通过 Socket 连接进行心跳检查。

如果系统时钟设置的时间比超时时间长,调度器会认为它超时,但实际上不是。

有没有人遇到过同样的问题,你是怎么解决的?

编辑

在我的 HA 产品中,当重负载阻塞系统时,我使用 Watchdog 杀死操作系统(所谓的自杀策略)。我必须在内部喂狗以防止意外自杀,使用 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 回答