任何基于独立于系统时钟的自由运行驻留线程的方法?

时间:2013-04-11 07:07:53

标签: java timer scheduler thread-sleep system-clock

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

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”之类的东西来设置你的系统时钟,等待几分钟,你会看到输出中发生了什么。

这很难过,因为在我的产品中,很多东西都是基于系统时钟的,

通过Socket连接为心跳检查器安排Scheduler(最后调用LockSupport.park)。

如果系统时钟的前置时间超过超时时间,则调度程序会将其视为超时,但实际上并非超时。

任何人遇到同样的麻烦,你是如何解决的?

修改

在我的HA产品中,我使用Watchdog在重负载阻塞系统时杀死操作系统(所谓的自杀策略)。我必须在内部喂狗以防止不必要的自杀,使用ThreadSupport.parkNanos(xxx)会有意想不到的自杀

2 个答案:

答案 0 :(得分:1)

我要做的是定期进行睡眠唤醒,例如每秒,5秒或分钟。如果你想调整时间,它可以检查currentTimeMillis(),或者你想要单调增加时间nanoTime()。

答案 1 :(得分:0)

最后,我在Linux中使用JNI来解决这个问题。在Java范围内确实没有出路。

#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);
    }