Altair Jones
Altair Jones

Reputation: 904

Java real fixed time interval

I'm doing some tasks using Java. I have some problems with timing: I need to set up a timer with a fixed period of repetition. I tried both, the standard Timer, and TimerTask and the ScheduledExecutor, but both work in an approximate manner, i.e. if I set an interval of 40 milliseconds, using the following code (for Executors)

m_executor = Executors.newScheduledThreadPool(5);       
Runnable thread = new TheThread();
m_executor.scheduleWithFixedDelay(thread, 0, 40000000, TimeUnit.NANOSECONDS);

And then I try to print "time" of each execution

private static final class TheThread implements Runnable {
    @Override
    public void run() {
        System.out.println(System.nanoTime()/1000000);
    }
}

The result is something like this:

xxxxxx300
xxxxxx345
xxxxxx386
xxxxxx428
...

As you can see, if I correctly understand nanoTime() the function is called at a random intervals, close to that I specified (40 milliseconds), but not exactly what I specified!

When I worked with C and Win32s, for example, I was able to use the CreateTimerQueueTimer() function that is highly accurate, and the callback function was called every 40 milliseconds:

xxxxxx300
xxxxxx340
xxxxxx380
...

I tried to move time measurement to avoid the printing time. I also tried to use scheduleAtFixedRate(), but unfortunately the period varies between 35 and 47 ms (set to 40 in the method).

I'm wondering how people can make software such emulators or similar things, that requires a precise period observance...:-)

I thought of a possible solution that I would like to show you and ask to you, experts:) how this idea could be applicable (and safe)

The problem here is to run some methods every X milliseconds, say 40 ms. The question here is about Java timer/timing, but what about this simple solution?

public class MyEmulator extends Thread {
    private long start = 0;
    private long end = 0;

    @Override
    public void run() {
        long exec_time; 

        start = System.nanoTime();
   
        /*
         * Do the emulator-loop
         */

        end = System.nanoTime();

        exe_time = (end - start)/1000000;

        // wait with a whil() (40 - exec_time)
    }
}

With this solution, when I print the elapsed time after the waiting whilt() is ended the result is exactly 40 ms (without decimal, that is not quit important).

Do you think it would be safe, i.e. are really 40 ms?

Upvotes: 2

Views: 949

Answers (1)

Brian Agnew
Brian Agnew

Reputation: 272347

I don't think you're going to be able to manage this in Java with this level of precision. Unlike your C/Win32 solutions, your Java solution is running in a JVM with multiple threads (of varying priority) and with garbage collection running and taking resources.

Having said that, I would experiment with the scheduleAtFixedRate() method, which executes at a regular period. scheduleWithFixedDelay() will execute and upon completion delay for a fixed amount of time. Hence not accounting for the time taken for your method to actually run.

Upvotes: 4

Related Questions