0

This piece of code will not be blocked. Though main method will wait at thread, but it seems this object will invoke this.notifyAll?

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        thread.join();
        synchronized (thread) {
            thread.wait();
        }
        System.out.println("stop");
    }
}
matt
  • 10,892
  • 3
  • 22
  • 34

2 Answers2

0

Answering just the question in your title:

Does a thread run this.notifyAll when its run method is over?

The documentation for Oracle's Java 12 edition says, Yes, the join() method calls wait() waiting for a notification that the thread has terminated.

But note! It also says, "It is recommended that applications not use wait, notify, or notifyAll on Thread instances." It also says, "...this implementation..." Some other Java Run-time Environment might implement thread.join() in a different way, and a program that depends on a Thread object to be notify()ed when the thread terminates might not work if you run it on the other JRE.


Also, see @akuzminykh's answer. Summary:

The notify() and notifyAll() methods do not do anything at all unless some other thread already is waiting in a wait() call. If your program terminates by itself, that's nice, but you should not depend on it to terminate by itself. By the time the main thread calls thread.wait() there's no reason to expect that any other thread will call thread.notify(), and so there's no reason to expect that the thread.wait() won't wait forever.


I'm just curious about the mechanism of join...

Take a look at the source code for the OpenJDK version of the Thread class.

http://hg.openjdk.java.net/jdk10/jdk10/jdk/file/777356696811/src/java.base/share/classes/java/lang/Thread.java

The join() method just calls join(0), and in the special case where the millis argument to join(long millis) is zero, all it does is this:

while (isAlive()) {
    wait();
}

In other words, all it does is wait() until the thread is not alive.

Note! You won't find the notify() call in the Thread.java source file. The notification happens somewhere else (maybe native code?) after the thread's run() method either returns or throws an exception.

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

This answer assumes that the given code is the one you've used and it actually does finish when you run it.

The given code is not "supposed" to finish under "normal" circumstances. As the wait happens after join, it's impossible that the terminated thread notifys the main-thread somehow. So why does it finish?

You could be a "victim" of a spurious wake-up. This happens when the JVM wakes up a thread "without a reason" from the programmer's perspective. Check out the related JLS part about wait:

Implementations are permitted, although not encouraged, to perform "spurious wake-ups", that is, to remove threads from wait sets and thus enable resumption without explicit instructions to do so.

Notice that this provision necessitates the Java coding practice of using wait only within loops that terminate only when some logical condition that the thread is waiting for holds.

Notice that this is one of the reasons you should always use wait in a loop.

In other words: A JVM is allowed to wake up a thread by itself. This can have e.g. performance reasons. Notice that there are many JVM implementations out there. The code you write is Java but the virtual machines that run the code can have different behaviours. Notice that Java runs on different platforms, hardware and so on, which makes different JVM implementations/behaviours necessary.

A spurious wake-up is a speciality and rather rare. It should definitely not occur in simple code like this. But it seems that this is the case here.


Just to be complete:

Yes, a thread calls this.notifyAll when it finishes. Check out Thread#join:

[...] As a thread terminates the this.notifyAll method is invoked. [...]

But as already explained, it's not the cause for the effect that you're essentially asking about.

akuzminykh
  • 4,522
  • 4
  • 15
  • 36