36

I'm wondering what the most accurate way of converting a big nanoseconds value is to milliseconds and nanoseconds, with an upper limit on the nanoseconds of 999999. The goal is to combine the nanoseconds and milliseconds values to ensure the maximum resolution possible with the limit given. This is for comparability with the sleep / wait methods and some other external library that gives out large nanosecond values.

Edit: my code looks like the following now:

while (hasNS3Events()) {                                
    long delayNS = getNS3EventTSDelay();
    long delayMS = 0;
    if (delayNS <= 0) runOneNS3Event();
    else {
        try {
            if (delayNS > 999999) {
                delayMS = delayNS / 1000000;
                delayNS = delayNS % 1000000;
            }

            EVTLOCK.wait(delayMS, (int)delayNS);
        } catch (InterruptedException e) {

        }
    }
}

Cheers, Chris

Chris Dennett
  • 22,412
  • 8
  • 58
  • 84
  • 1
    it is worth noting that this time is a hint to the OS to wait at least this long. In Windows and Linux, the delay is usually within 2 ms, but it can be much long. IMHO You shouldn't worry about the nano-second timing as you are highly unlikely to see any difference. – Peter Lawrey Nov 29 '10 at 08:31

4 Answers4

113

For an ever shorter conversion using java.util.concurrent.TimeUnit, equivalent to what Shawn wrote above, you can use:

    long durationInMs = TimeUnit.NANOSECONDS.toMillis(delayNS);
Ibrahim Arief
  • 8,742
  • 6
  • 34
  • 54
105

Why not use the built in Java methods. The TimeUnit is part of the concurrent package so built exactly for you needs

  long durationInMs = TimeUnit.MILLISECONDS.convert(delayNS, TimeUnit.NANOSECONDS);
Luhar
  • 1,859
  • 2
  • 16
  • 23
Shawn Vader
  • 12,285
  • 11
  • 52
  • 61
  • 8
    This method truncate to 0 if, for example, 999999 nanoseconds was used – Gilian Apr 29 '16 at 00:02
  • 1
    This does not work and also does not answer the question. The question was to convert to millis AND nanos, wchich you need for example for the Thread.sleep(millis, nanos) call. – Christian Esken Mar 06 '17 at 17:51
29

Just take the divmod of it with 1000000.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
1

The TimeUnit.timedWait(Object obj, long timeout) is what you should use. It does this calculation for you and then calls wait on the object.

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html#timedWait(java.lang.Object,%20long)

The implementation from Java 8 (to see that it is computing the ms and ns based off nanoseconds):

public void timedWait(Object obj, long timeout)
        throws InterruptedException {
    if (timeout > 0) {
        long ms = toMillis(timeout);
        int ns = excessNanos(timeout, ms);
        obj.wait(ms, ns);
    }
}

So you would use

TimeUnit.NANOSECONDS.timedWait(EVTLOCK, delayNS);

There are also sleep and timedJoin methods that are similar.

Randall T.
  • 187
  • 12