Reputation: 92
How can I achieve accurate timing in Java? I know Thread.sleep() is inaccurate and leads to InterruptedExceptions. I'm trying to make a physics simulator and I want to have accurate code. Here is my code so far:
public class FreeFall() {
public static void main(String[] args) {
double height = Double.parseDouble(args[0]);
double xi = height;
int counter = 0;
while (true) {
height = xi + 9.8 / * counter * counter;
System.out.println(height);
counter++;
Thread.sleep(1000);
}
}
}
Upvotes: 2
Views: 4090
Reputation: 340118
Conventional implementations of Java are not real-time systems. So you cannot count on deterministic performance.
If you insist on deterministic timing, seek out an implementation of real-time Java.
Similar Question: Java - alternative to thread.sleep
Thread.sleep
You can ask for sleeping with a resolution of nanoseconds, but you may not get it due to limitations of current computer hardware. See the other sleep
method taking a second argument for nanoseconds.
Thread.sleep( 0L , 300L ) ; // Ask to sleep 300 nanoseconds.
The behavior of Thread.sleep
is never deterministically reliable, as discussed below. Many factors such as internal CPU scheduling (such as out-of-order execution and hyper-threading), OS scheduling of the JVM, the JVM’s scheduling of threads, and occasional garbage collection all impact the actual execution timing. So you can never count on predictable execution unless you move to a real-time Java implementation.
System.nanoTime
To track elapsed time, call System.nanoTime
. This has a resolution of nanoseconds, but not likely precision. As of 2018, conventional computer hardware clocks are only accurate to a range of around microseconds, not nanoseconds. This is good for things such a micro-benchmarking (tip: JMH). The System.nanoTime
has nothing to do with telling the current date-time. The number returned is a count from some undocumented origin moment (in my experience, since the JVM launched, but not guaranteed). The 64-bit number may overrun in a few decades of continual running.
long start = System.nanoTime() ; // Just some progressively incrementing number of nanoseconds. NOT the current date-time.
long stop = System.nanoTime() ;
long elapsed = ( stop - start ) ; // Calculate elapsed time in a resolution as fine as nanoseconds (though not likely precise beyond microseconds).
Instant
To get the current moment in UTC with a resolution of nanoseconds, use java.time.Instant
class. In Java 8, the current moment could captured only to milliseconds, but in Java 9 and later a fresh implementation of Clock
may deliver finer resolution. I am seeing microseconds captured in Oracle JDK 9.0.4 on macOS Sierra.
Instant instant = Instant.now() ; // Capture the current moment in UTC with a resolution of nanoseconds though likely with precision not as fine.
2018-03-16T01:18:54.898583Z
Duration
I suggest generally using the Instant
objects as-is. You can compare via isBefore
, isAfter
, and equals
methods. To calculate elapsed time, use Duration.between
.
Duration d = Duration.between( instantThen , Instant.now() ) ; // A span of time not attached to the timeline, with a resolution of nanoseconds.
System.currentTimeMillis()
As for System.currentTimeMillis()
, you can forget about this method. You are better off using Instant
instead.
As for Timer
and TimerTask
, you should know that those classes are now legacy, supplanted by the more sophisticated Executor framework added to Java 5 and later. See the Oracle Tutorial.
Even with Executors, you cannot expect exact split-second accuracy in execution. The host OS controls scheduling the JVM, and its performance may vary. Within the JVM, threads are scheduled dynamically, and their performance may vary. In particular, garbage collection may impact performance at particular moments.
If you want deterministic timing of execution, you need to obtain an implementation of real-time Java. The conventional implementations of Java such as the Oracle JDK and OpenJDK are most certainly not real-time systems.
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
Upvotes: 6
Reputation: 117
For Java 8 and above - You can use java.time library It has date time classes
For Date -
//To create a new date
LocalDate ld = LocalDate.Of(2018,March,26);
//To print current date
LocalDate.now();
For Time -
//To create a new time
LocalTime lt = LocalTime.Of(11,22);
//To print current time
Local time.now();
For both Date and Time -
//To create a new date time
LocalDateTime ldt = LocalDateTime.Of(2018,March,26,11,22);
//To print current date time
LocalDateTime.now();
Note : Please take care of these things - -These classes are only available in Java 8 and above. -These classes has private constructor, so you can't instantiate them -Of is a static method and hence called using class name -These classes are immutable, and hence any update you need to create is to saved into a new object
Upvotes: 0
Reputation: 10696
You might want to make use of timestamps, taking advantage of System.currentTimeMillis()
, which will give you elapsed milliseconds since 1 Jan 1970.
Take a timestamp when your object starts to fall. Then, within your loop, you can take a timestamp representing the current time. Subtract startTime
from currentTime
and you get an accurate number of milliseconds. From this, for example you can calculate how far your object should have fallen over that period of time given a constant speed.
The nice thing about this approach is that it doesn't matter whether you're running on a fast or slow processor, since your timestamps reflect the actual passage of time vs. the number of iterations of your loop.
Upvotes: 2