Running wait () on a Thread instance from main () in Java

I play with the temporary version of wait () in java.lang.Object and noticed that it acts differently in two different scripts.

Scenario 1: using the default run () definition in a thread

public static void main (String[] args) throws InterruptedException { Thread t = new Thread(); t.start(); System.out.print("X"); synchronized(t) { t.wait(10000);} System.out.print("Y"); } 

Questions about scenario 1: I experience a delay between X and Y. Is it because I call wait () from the main (albeit on t), and therefore the call stack of the main is used by the thread, and not the second thread?

Scenario 2: Thread on-fly subclasses to override run () for printing. A.

 public static void main (String[] args) throws InterruptedException { Thread t = new Thread() {public void run() {System.out.print("I am the second thread.");}}; t.start(); System.out.print("X"); synchronized(t) { t.wait(10000);} System.out.print("Y"); } 

Questions about scenario 2: I do not experience any delay at all! What has changed only because I redefined run ()? Now, every time I run the program, it immediately prints “XI am the second thread.Y” without any delay, whatsoever! Where did the wait () effect go?

+8
java multithreading synchronized wait
source share
2 answers

The explanation of how thread termination sends a notifyAll notification is correct and correct, +1 from me. I will try to add some information on why this is relevant.

When you call

 synchronized(t) { t.wait(10000);} 

in the main thread, this is the main thread that performs the wait. t is the monitor that is waiting for the main thread. Your expectation that this will cause your thread t become inactive is wrong.

The monitor here (a shared object that is locked, which is t ) is used to communicate between different threads, the thread calls notifyAll on the monitor, and other threads waiting on the monitor receive a notification. You can consider the monitor as a common point of communication.

In the first example, thread t starts and ends immediately (because it has nothing to do). The thread ends and sends its notification before the main thread starts to wait, so you will see a delay before the timeout expires.

In the second example, stream t has something to print, between it and the main stream there is a race condition. It is free for everyone, what happens first of all depends on the randomness of time. What you see is that thread t should now print the line to the console, so it manages to stay busy long enough to keep it alive while the main thread starts to wait, allowing the main thread to receive a notification when t ends, forcing the main thread to reduce latency.

+1
source share

In fact, you are faced with why you should NEVER call wait or notify(All) in a thread (see JavaDocs for Thread). Internally, Thread uses wait and notifyAll to implement Thread.join (), so in the second case, you enter a thread, but then another thread dies and calls notifyAll (), which wakes up your main thread.

Use Thread.sleep if you just want to wait for the elapsed time, use Thread.join if you really want to wait for the threads to finish. Also read javadocs in Object for proper use of wait , notify and notifyAll .

javaDoc :

 public final void join(long millis) throws InterruptedException 

It expects no more than milliseconds of milliseconds for this thread to die. A timeout of 0 means waiting forever. This implementation uses the this.wait call loop due to this. As the thread completes this.notifyAll is called. It is recommended that applications do not use wait, notify, or notifyAll for Thread instances.

+6
source share

All Articles