"Hi, Amigo!"

"Hi, Rishi!"

"I'm going to introduce you to the Object class's wait, notify, and notifyAll methods."

"Today we'll just get acquainted with them, but we'll come back later and spend more time on this."

"Okay."

"These methods were invented as part of the thread synchronization mechanism."

"Let me remind you that Java has a built-in mechanism for controlling access to shared resources (objects) from different threads. A thread can declare that an object is busy, and other threads will have to wait until the busy object is released."

"I remember. You do that using the synchronized keyword."

"Right. Typically, the code would look something like this:"

public void print()
{
 Object monitor = getMonitor();
 synchronized(monitor)
 {
  System.out.println("text");
 }
}

"Remember how that works?"

"Yep. If two threads simultaneously call the print() method, one of them will enter the block labeled synchronized and lock the monitor, which makes it so the second thread will wait until the monitor is released."

"Right. Once a thread enters the block labeled synchronized, the monitor object is marked as busy, and other threads will be forced to wait for the monitor object to be released. The same monitor object can be used in various parts of the program."

"By the way, why did you choose the name monitor?"

"A monitor is what you usually call an object that stores the busy or free status."

"And this is where the wait and notify methods come into play."

"Actually, these are really the only two methods. The others are just adaptations of these methods."

"Now let's wrap our heads around what the wait method is and why we need it."

"Sometimes there are situations in a program where a thread enters a block of synchronized code and locks the monitor, but can't keep going because it is missing some data. For example, a file it needs to process hasn't finished downloading or something like that."

"We could just wait for the file to be downloaded. You could just check it using a loop. If the file hasn't downloaded yet, then sleep for a second or so, and check again until it is downloaded."

"Something like this:"

while(!file.isDownloaded())
{
 Thread.sleep(1000);
}
processFile(file);

"But in our case, this type of waiting is too expensive. Since our thread locked the monitor, other threads are also forced to wait even though they may already have the data they need."

"The wait() method was invented to solve this problem. This method causes the thread to release the monitor and then «suspends» the thread.

"You can only call a monitor object's wait method when the monitor is busy, i.e. only inside a synchronized block. When this happens, the thread temporarily stops running, and the monitor is released so that other threads can use it."

"There are often instances where a thread will enter a synchronized block and call wait, thus releasing the monitor."

"Then a second thread will enter and be suspended, then a third, and so on."

"And how does a thread get resumed?"

"For that, there is a second method: notify."

"You can only call a monitor object's notify/notifyAll methods when the monitor is busy, i.e. only inside a synchronized block. The notifyAll method wakes up all threads that are waiting on this monitor object."

"The notify method 'unfreezes' one random thread, but the notifyAll method unfreezes all of this monitor's «frozen» threads."

"Very interesting. Thank you, Rishi."

"There are also adaptations of the wait() method:"

wait() method Explanation
void wait(long timeout)
The thread «freezes», but it automatically «unfreezes» after waiting the number of milliseconds passed to the method as an argument.
void wait(long timeout, int nanos)
The thread «freezes», but it automatically «unfreezes» after waiting the number of nanoseconds passed to the method as an argument.

"We also call this a wait with a timeout. The method works like a normal wait, but if the specified time has passed and the thread hasn't been woken up, it wakes itself up."