Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am playing around with the timed version of wait() in java.lang.Object and have observed that it acts differently in two different scenarios.

Scenario1: Using the default definition of run() in 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 on scenario1: I am experiencing a delay between X and Y. Is this because I am calling wait() from main (even though, on t) and therefore the call stack of the main thread is being used, rather than that of the second thread?

Scenario2: Subclassing Thread on-the-fly to override run() in order to print something.

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 on scenario2: I am NOT experiencing any delay at all! What has changed just because I have overridden run()? Now, each time I run the program it immediately prints "XI am the second thread.Y" without any delay, whatsoever! Where has the effect of wait() gone?

like image 635
softwarelover Avatar asked Jun 02 '15 13:06

softwarelover


People also ask

Is wait () in thread class?

wait() method is a part of java. lang. Object class. When wait() method is called, the calling thread stops its execution until notify() or notifyAll() method is invoked by some other Thread.

How can use Wait method in thread?

wait() causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0). The current thread must own this object's monitor.

When wait () method is invoked?

Whenever the wait() method is called on an object, it causes the current thread to wait until another thread invokes the notify() or notifyAll() method for this object whereas wait(long timeout) causes the current thread to wait until either another thread invokes the notify() or notifyAll() methods for this object, or ...

What is wait () and notify () in multithreading?

The wait() method is defined in the Object class. The notify() method is defined in the Object class. 4. The wait() method is used for interthread communication. The notify() method is used to wake up a single thread.


2 Answers

You have actually run into exactly why you should NEVER call wait or notify(All) on Thread (see the JavaDocs for Thread). Internally, Thread uses wait and notifyAll to implement Thread.join(), so what's happening in the second case is you thread enters wait, but then the other thread dies and calls notifyAll(), which wakes up your main thread.

Use Thread.sleep if you just want to wait for an elapsed time, use Thread.join if you actually want to wait for the thread’s termination. Also, read the javadocs in Object for proper usage of wait, notify, and notifyAll.

javaDoc:

public final void join(long millis)
                throws InterruptedException

Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever. This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

like image 165
ControlAltDel Avatar answered Oct 12 '22 22:10

ControlAltDel


The explanation about how the thread finishing sends a notifyAll is relevant and correct, +1 from me. I'll try to add some information about why this is relevant.

When you call

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

in the main thread, it is the main thread that does the waiting. t is the monitor that the main thread is waiting on. Your expectation that this should make your t thread go dormant is mistaken.

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

In your first example, the thread t starts and finishes immediately (because it doesn't have anything to do). The thread finishes and sends its notification before the main thread starts waiting, so you see a delay until the wait times out.

In the second example, the thread t has something to print, there's a race condition between it and the main thread. It's a free-for-all, what happens first depends on accidents of timing. What you're seeing is that the thread t now has to print a line to the console, so it manages to keep busy long enough that it's still alive at the time the main thread starts to wait, allowing the main thread to receive the notification when t finishes, causing the main thread to cut its wait short.

like image 33
Nathan Hughes Avatar answered Oct 12 '22 22:10

Nathan Hughes