1
votes

In Java, there are two ways of accessing time, System.currentTimeMillis and System.nanoTime. The first is similar to a wall clock, and can change time based on leap seconds, and other OS caused time changes. Because of this, measuring durations of time is better suited to use nanoTime which is more accurate and usually more precise.

With that in mind, why does Thread.join() use the currentTimeMillis instead of nanoTime?

The code in question is:

    public final synchronized void join(long millis) throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}
1
Because caller(s) expect it to timeout like "a wall clock". - Elliott Frisch
Because join() is @since 1.0 and nanoTime()isn't, and changing the behaviour would have been poor practice. - user207421
Changing error prone behavior to less error prone is a valid though. Regardless of when join() was added, it can be reimplemented at any version. - Carl Mastrangelo
@eliott Really? If you write wait(1h) you expect the code to return immediately once a year? Honestly it's annoying behaviour (and runs counter to what "wait an hour" means colloquially) but that's how it's specified and since the problem comes up exceedingly rarely it's not a big problem in practice. - Voo

1 Answers

0
votes

This actually is a bug, and was reported in JDK-8098798 and JDK-8200284. It has been fixed in JDK 12.