Java - Creating an Internal Clock

2019-07-04 03:30发布

问题:

I wish to calculate the time passed in milliseconds from a specific time in Java.

The classic way it to use System.currentTimeMillis(); for the starting time, and then use this again with the previous one to get the elapsed time. I wish to do something similar to this, but NOT rely on the system time for this.

If I rely on the system time, the user of the program could manipulate the system clock to hack the program.

I have tried using code similar to the following:

int elapsed = 0;
while (true) {
    Thread.sleep(10);
    elapsed += 10;
}

This works, but I it is not too reliable in the case that the computer lags and then locks up for a second or two.

Any ideas anyone?

回答1:

You want to utilize System.nanoTime. It has no relation to the system clock. It can only be used to track relative time which seems to be all you want to do.

In an effort to prevent this answer from just being a link to another answer here is a short explanation.

From Documentation

public static long nanoTime() Returns the current value of the most precise available system timer, in nanoseconds.

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees are made about how frequently values change. Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.

Yet another link to timer information: https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks

You could use Java's Timer class to spawn a "check" callback at some specific precision, lets say every 500ms. This callback would not be used to determine that 500ms actually did pass. You would call System.nanoTime in the callback and compare it to the last time you called System.nanoTime. That would give you a fairly accurate representation of the amount of time that has passed regardless of the wall clock changing.

You can take a look here: System.currentTimeMillis vs System.nanoTime