1

To make the current thread to park for a specified timeout,i can use:

LockSupport.parkNanos(long nanos);

or

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

Unfortunatly,the internal ticking of this two method are all base on the system-clock.

If the system-clock is changed(by ntptime or manually) during the waiting period,these method would not acting as excpected.

for example, in t0,i invoke this method like Thread.sleep(dt) to sleep dt seconds. During the waiting period, i set my system-clock ahead 20 seconds,then the thread will sleep for actully dt+20 seconds.

use the following code to check it:

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

use something like "date && sudo date -s 16:10:40" to set your system clock ahead for few minites during waiting, and you will see what happend from the output.

That's sad,because in my product,many things are base on system clock,

such as Scheduler(invoking LockSupport.park finally) for a heartbeat checker via a Socket connection.

If the system clock was set forward longer than the timeout,the Scheduler will consider it timed out,but actually not.

Any one encountered the same trouble and how do you solve it?

EDIT:

In my HA product,i using Watchdog to kill the os when a heavy-load is blocking the system(so called suicide strategy). I have to feed the dog internally to prevent unwanted suicide,Using ThreadSupport.parkNanos(xxx) will have unexpected suicide

BlackJoker
  • 3,099
  • 2
  • 20
  • 27
  • Are you looking for a Java interface to the POSIX function [clock_nanosleep](http://linux.die.net/man/2/clock_nanosleep)? AFAIK Java does not support monotonic clocks at all. – nosid Apr 11 '13 at 17:26
  • @nosid,yes i think this problem can't be solved in java,so i'm searching some working aroud to minimize the effect. – BlackJoker Apr 12 '13 at 15:39

2 Answers2

1

What I would do is have the sleep wake periodically e.g. every second, 5 seconds or minute. It can check the currentTimeMillis() if you want the adjusted time, or nanoTime() is you want a monotonically increasing time.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I will consider the practicability in my product,thanks any way. – BlackJoker Apr 11 '13 at 07:27
  • Waking every second has very little overhead unless you have a large number of threads (in which case I suggest you have less threads) A CPU can process over 10 billion instructions in a second and it is an eternity to a computer. – Peter Lawrey Apr 11 '13 at 07:29
  • Yeah,so maybe i can design a scheduler base on this,split long delay inot pieces,use nanoTime(),but may lose some precision – BlackJoker Apr 11 '13 at 07:36
  • The schedule is only accurate to about 1 ms at best and I have seen delays of 40 ms on a busy machine. i.e. it wakes 40 ms late. As you don't have a real time system you should assume it is too accurate anyway. – Peter Lawrey Apr 11 '13 at 07:40
  • consider this:i want to sleep 10s,split to 1s 10 times,if when time is 500ms,set the clock ahead 100s,then this sleep will be waken up after 100s +500ms later,that does not solve the problem – BlackJoker Apr 11 '13 at 07:49
  • The problem as you state it cannot be solved. The task can execute in the past. – Peter Lawrey Apr 11 '13 at 07:53
0

Finally,I used JNI in Linux to solve this problem.There is indeed no way out in Java scope。

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

and the java class looks like:

public class LinuxSleeper extends CommonSleeper implements Sleeper {

    static {
        NativeUtils.loadLibrary("LinuxSleeper");
    }
@Override
    public int sleep(int seconds) {
     ///....
    }
    private native int sleep0(int seconds);
    }
BlackJoker
  • 3,099
  • 2
  • 20
  • 27