The notion of time in Java with System.currentTimeMillis() and System.nanotime()

Behavior of System.currentTimeMillis()

What do you get when you execute?

System.out.println(System.currentTimeMillis());
Thread.currentThread().sleep(1);
System.out.println(System.currentTimeMillis());

The result is
1365436257623
1365436257623

Weird weird we try again by introducing a loop to check the result on a minute

for(int i=0 ; i<1000 ; i++){
System.out.println(System.currentTimeMillis());
Thread.currentThread().sleep(1);
}

I won’t give all the trace but it’s similar to

1365436715292
1365436715292
1365436715292
1365436715292
1365436715292
1365436715292
1365436715292
1365436715292
1365436715308
1365436715308
1365436715308
…..
Julius Davies notice a change every x ms where x is often 10 but not necessarily. In fact the return of the System.currentTimeMillis() method depends on the operating system on which you run the command.

Behavior of System.nanoTime()

Since Java 5 a new nanotime() method has been added in the System class. Let’s go back to our initial test
for(int i=0 ; i<1000 ; i++){
System.out.println(System.nanoTime());

Thread.currentThread().sleep(1);

}

the log is as follows
142601475743425
142601477181038
142601479133800
142601481086842
142601483037928
142601485015833
142601486945687
142601488907389
142601490866855
142601492805370

At first glance, we obtain a more relevant result.

Is this nanotime method the miracle solution?

Well, it’s not. Don’t replace all your currentTimeMillis with nanotimes… You are alerted in the javadoc of the method

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time…This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) – no guarantees are made except that the resolution is at least as good as that of currentTimeMillis().

The value returned by this method represents the number of nanoseconds calculated from a fixed date but whose origin changes. You will have the same origin in one instance of the JVM but it will potentially not be the same in another.

Moreover the returned value is accurate to the nanosecond but does not represent the current date!

An example

System.out.println(new Date(System.currentTimeMillis()));
System.out.println(new Date(System.nanoTime()/1000));

will give
My Apr 22 14:20:49 CEST 2013
Killed Nov 19 00:25:18 CET 1974

There are two methods to recover a time because we have two different needs

currentTimeMillis or nanoTime?

In a system we can have two date-related needs
read a time value, and
program / trigger a time-dependent event
The term clock is often used to refer to these two notions because time is read on a clock, and an alert is triggered when the clock reaches a certain time. We will limit the term clock to the first case and we will speak of Timer (literally timer) for the second.

Time is generally read in milliseconds. Time-related events are triggered by interruptions at the OS level which are usually done every 10 ms (it is necessary to give time to the other operations launched). This delay can sometimes be set at OS level and is the delta observed above in the successive call of the currentTimeMillis function.

When one wishes to use a timer or calculate a time of execution one would need a clock giving the time to the microseconds and not every 10ms. This is why systems often have a different resolution than the absolute clock (time-of-day clock) and the relative execution time (free-running relative clock).

The nanoTime method uses the clock with the highest resolution on a platform and even if the returned value is in nanoseconds, the update frequency is every milliseconds. Note that on some older systems (old versions of Linux or Windows 98), the relative time is defined from the absolute time (updated every 10ms). One can have very important differences of behavior from one system to another and one should neither blame the VM nor the operating system but rather the hardware calculating the times.

Implementation of these methods

If we look at the signature of these methods in the System class we have

public static native long currentTimeMillis();
public static native long nanoTime();

We can observe the native modification of these methods that we do not often use in our business applications. It allows you to define the call to a method that is not included in the FMV.

Follow Us