0
//jdk7-Thread.java
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); //why is wait() called for loop in Thread.join() of Java?
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

Because calling once can let the main thread wait, calling for loop also can let the main thread wait, so why calls wait() for loop?

B_qxzb
  • 9
  • 2
  • Documentation for `wait(long)`: "A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops" – user85421 Nov 02 '18 at 14:45
  • also, *anyone* can call notify on the Thread and make it wake up from `wait`... not restricted to Thread ending – user85421 Nov 02 '18 at 14:58

2 Answers2

3

You are correct that the call to wait() (at least in the first loop) could be eliminated. The logic of the second loop would have to be changed a bit, but the call to wait(delay) could be eliminated there as well.

However, eliminated the calls to wait would change the loops from an efficient, low-impact way of waiting for something to happen into an inefficient busy wait that would waste CPU time and energy. Busy waiting is usually considered a last-resort technique for waiting for a condition to become true.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • Nope, it could not be eliminated - the `wait` can (rarely) exit without any reason and, most important, `notify()` can be called on the Thread by *anyone* (having a reference to it) {and we should have a beer [:-) } – user85421 Nov 02 '18 at 14:51
  • @CarlosHeuberger - It doesn't matter why `wait()` exits. It doesn't matter that another thread can call `notify()`. The only thing the loop does is repeatedly check whether `isAlive()` returns `true`. Once it returns `false`, the loop exits. If you eliminate the `wait()` the same thing happens--the loop exits when `isAlive()` returns `false`. The only thing that changes is that the loop needlessly makes that check much more often instead of waiting to be notified that it might be a good time to check. P.S. I'm up for a beer! :) – Ted Hopp Nov 02 '18 at 14:58
  • ups, sure, sorry, I miss-interpreted that the loop could be eliminated... – user85421 Nov 02 '18 at 14:59
  • @CarlosHeuberger - Ah. Yes, eliminating the loop entirely would screw things up quite a bit! – Ted Hopp Nov 02 '18 at 15:00
2

t.join() must not return until the thread has terminated. But just because the wait() call returns, that does not mean that the thread is terminated. The method keeps looping until isAlive() returns false.

NOTE: One reason why wait() could return while the thread still is alive is, nothing in the design of the Thread class prevents the caller from waiting on, and notifying a Thread instance for other purposes.

There are other reasons as well. Read the Guarded Blocks Tutorial for a thorough description of how to use wait() and notify() including the several reasons why you should always wait() in a loop.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57