views:

2156

answers:

9

Does anyone know a Library which provides a Thread.sleep() for Java which has an error not higher than 1-2 Millisecond?

I tried a mixture of Sleep, error measurement and BusyWait but I don't get this reliable on different windows machines.

It can be a native implementation if the implementation is available for Linux and MacOS too.

EDIT The link Nick provided ( http://blogs.sun.com/dholmes/entry/inside_the_hotspot_vm_clocks ) is a really good resource to understand the issues all kinds of timers/sleeps/clocks java has.

+1  A: 

Use one of the Thread::join overrides on the current thread. You specify the number of milliseconds (and nanoseconds) to wait.

1800 INFORMATION
So if I'm wrong, please point out why instead of just silently voting down, thanks
1800 INFORMATION
The nano-second are rounded to the milli-second for wait and join.
Peter Lawrey
+2  A: 

There are no good reasons to use Thread.sleep() in normal code - it is (almost) always an indication of a bad design. Most important is, that there is no gurantee that the thread will continue execution after the specified time, because the semantics of Thread.sleep() is just to stop execution for a given time, but not to continue immedeately after that period elapsed.

So, while I do not know what you try to achieve, I am quite sure you should use a timer instead.

Daniel Brückner
Im playing with diffrent kinds of Gameloops and as i dont want to waste all the CPU after logic and rendering are done (there isnt too much to draw and calculate in a Tetris clone) i need a method to suspend my Program.But because I didn't want to start a discussion about how GameLoops are Designed I created a question about how I can suspend my code for a specific amount of time.
HaBaLeS
@haBaLeS Generally I would consider using something like a CyclicBarrier if I am at all understanding where you are coming from.
Adam Jaskiewicz
+1  A: 

JDK offers the Timer class.

http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html

Reading the docs clearly indicates that beyond the plumbing to make this a generalized framework, it uses nothing more sophisticated than a call to Object.wait(timeout):

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#wait(long)

So, you can probably cut the chase an just use Object#wait yourself.

Beyond those considerations, the fact remains that JVM can not guarantee time accuracy across platforms. (Read the docs on http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#currentTimeMillis())

I think you'll need to experiment with a compromise solution combining Timer and busy polling if you want to want the highest timing precision possible on your platform. Effectively Object#wait(1) -> System#nanoTime -> calculate delta -> [loop if necessary].

If you are willing to roll your own, JNI pretty much leaves it wide open for platform specific solutions. I am blissfully un-aware of Window's internals, but obviously if the host OS does provide sufficiently accurate realtime timer services, the barebones structure of setting up a timerRequest(timedelta, callback) native library shouldn't be beyond reach.

A: 

Sounds like you need an implementation of real-time Java.

Michael Borgwardt
+5  A: 

To improve granularity of sleep you can try the following from this Thread.sleep page.

Bugs with Thread.sleep() under Windows

If timing is crucial to your application, then an inelegant but practical way to get round these bugs is to leave a daemon thread running throughout the duration of your application that simply sleeps for a large prime number of milliseconds (Long.MAX_VALUE will do). This way, the interrupt period will be set once per invocation of your application, minimising the effect on the system clock, and setting the sleep granularity to 1ms even where the default interrupt period isn't 15ms.

The page also mentions that it causes a system-wide change to Windows which may cause the user's clock to run fast due to this bug.

EDIT

More information about this is available here and an associated bug report from Sun.

Pool
This helped a lot. I ran tests on 2 different windows machines with different load and got a average error of 0.8ms. On a Linux I had an average error of 0.3ms - Thanx you saved my day :-)
HaBaLeS
Great, it is a shame it is a hack - I currently use similar but am yet to find an equally functional and elegant solution for Swing animation. If anyone is more enlightened....
Pool
A: 

You could try using the new concurrency libraries. Something like:

private static final BlockingQueue SLEEPER = new ArrayBlockingQueue(1);
public static void main(String... args) throws InterruptedException {
    for(int i=0;i<100;i++) {
        long start = System.nanoTime();
        SLEEPER.poll(2, TimeUnit.MILLISECONDS);
        long time = System.nanoTime() - start;
        System.out.printf("Sleep %5.1f%n", time/1e6);
    }
}

This sleeps between 2.6 and 2.8 milliseconds.

Peter Lawrey
You mean, "This sleeps between 2.6 and 2.8 _milliseconds_"?
João da Silva
Thank you, Joao. I do most of my timings in micro-seconds and I get them confused some times. :-/
Peter Lawrey
+1  A: 

The Long.MAX_VALUE hack is the working solution.

I tried Object.wait(int milis) to replace Thread.sleep, but found that Object.wait is as accurate as Thread.sleep (10ms under Windows). Without the hack, both methods are not suitable for any animation

+1  A: 

Hello! This is ~5 months late but might be useful for people reading this question. I found that java.lang.concurrent.locks.LockSupport.parkNanos() does the same as Thread.sleep() but with nanosecond precision (in theory), and much better precision than Thread.sleep() in practice. This depends of course on the Java Runtime you're using, so YMMV.

Have a look: LockSupport.parkNanos

(I verified this on Sun's 1.6.0_16-b01 VM for Linux)

João da Silva
A: 

Unfortunately, as of Java 6 all java sleep-related methods on Windows OS [including LockSupport.awaitNanos()] are based on milliseconds, as mentioned by several people above.

One way of counting precise interval is a "spin-yield". Method System.nanoTime() gives you fairly precise relative time counter. Cost of this call depends on your hardware and lies somewhere 2000-50 nanos.

Here is suggested alternative to Thread.sleep():

   public static void sleepNanos (long nanoDuration) throws InterruptedException {
        final long end = System.nanoTime() + nanoDuration;
        long timeLeft = nanoDuration;
        do {
            if (timeLeft > SLEEP_PRECISION)
                Thread.sleep (1);
            else
                if (timeLeft > SPIN_YIELD_PRECISION)
                    Thread.yield();

            timeLeft = end - System.nanoTime();
        } while (timeLeft > 0);
    }

This approach has one drawback - during last 2-3 milliseconds of the wait hit CPU core. Note that sleep()/yield() will share with other threads/processes. If you are willing to compromise a little of CPU this gives you very accurate sleep.

Andy Malakov