If interdependent threads share data that’s processed alternately by them, the threads should be able to communicate with each other to notify when there’s a completion of events, or else the threads might not work correctly.
Imagine you’re waiting for your friend to go river rafting at a camp. You check whether she has arrived by peeping out of your tent every minute. This can become quite inconvenient. How about asking her to notify you when she arrives? Let’s implement this in code using the wait and notify methods from class Object. Because these methods are defined in class Object, they can be called on any Java object. Methods wait(), notify(), and notifyAll() enable threads sharing the same data to communicate with each other.
Methods wait(), notify(), and notifyAll() are defined in class Object and not in class Thread.
To call wait() or notify() a thread must own the object’s monitor lock. So calls to these methods should be placed within synchronized methods or blocks. Here’s an implementation of the previous example in code:
Methods wait(), notify(), and notifyAll() must be called from a synchronized method or code blocks or else an IllegalMonitor- StateException will be thrown by the JVM.
All overloaded versions of wait() throw a checked InterruptedException. Methods notify() and notifyAll() don’t throw an InterruptedException.
Unlike the Thread’s method join(), which waits for another thread to complete its execution, methods wait() and notify() don’t require a thread to complete their execution. The thread that calls wait(), waits for another thread to notify it using method notify() or notifyAll(). Some other examples from daily life of using wait() and notify() are teachers and students waiting to be notified for a next workshop on life skills (which can happen multiple times), an operator who answers a phone whenever she’s notified of an incoming call, or customers waiting for notification of new offers on a range of televisions.
Multiple threads might deadlock when they have acquired a lock on objects and are waiting to acquire locks on additional objects that are owned by other waiting threads. Let’s discuss this threading issue in detail next.
//-------------Wait Notify Example-------//---Ex:1---packagecom.gs.corejava.datastructures;classPen {}classStudenttextendsThread {Pen pen;publicStudentt(Pen pen) {this.pen= pen; } @Overridepublicvoidrun() {System.out.println(String.format("%s Doing some work with pen ",this.getName()));System.out.println(String.format("%s Going to wait for pen ",this.getName()));pen.notify();try {pen.wait(); } catch (InterruptedException e) {e.printStackTrace(); }System.out.println(String.format("%s Wait over again using pen",this.getName())); }}publicclassWaitNotifyExample1 {publicstaticvoidmain(String[] args) {Pen pen =newPen();Thread st1 =newThread(new Studentt(pen));Thread st2 =newThread(new Studentt(pen));st1.start();st2.start(); }}//--------------Thread-2Doing some work with pen Thread-0Doing some work with pen Thread-2Going to wait for pen Thread-0Going to wait for pen Exception in thread "Thread-3"java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at com.gs.corejava.datastructures.Studentt.run(WaitNotifyExample1.java:20) at java.lang.Thread.run(Thread.java:619)Exception in thread "Thread-1"java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at com.gs.corejava.datastructures.Studentt.run(WaitNotifyExample1.java:20) at java.lang.Thread.run(Thread.java:619)//----------------//---Ex:2---pen.notify();synchronized (pen) {try {pen.wait(); } catch (InterruptedException e) {e.printStackTrace(); } }//--------------Thread-2Doing some work with pen Thread-0Doing some work with pen Thread-2Going to wait for pen Thread-0Going to wait for pen Exception in thread "Thread-3"java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at com.gs.corejava.datastructures.Studentt.run(WaitNotifyExample1.java:20) at java.lang.Thread.run(Thread.java:619)Exception in thread "Thread-1"java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at com.gs.corejava.datastructures.Studentt.run(WaitNotifyExample1.java:20) at java.lang.Thread.run(Thread.java:619)//-------------//---Ex:3---synchronized (pen) {try {pen.notify();pen.wait(); } catch (InterruptedException e) {e.printStackTrace(); } }//------------Thread-0Doing some work with pen Thread-2Doing some work with pen Thread-0Going to wait for pen Thread-2Going to wait for pen Thread-0Wait over again using penInfiniteWaitingfor Thread-2 as no onw to wake up//------------ //---Ex:4---packagecom.gs.corejava.datastructures;classPen {}classStudenttextendsThread {Pen pen;publicStudentt(Pen pen) {this.pen= pen; } @Overridepublicvoidrun() {System.out.println(String.format("%s Doing some work with pen ",this.getName()));System.out.println(String.format("%s Going to wait for pen ",this.getName()));synchronized (pen) {try {pen.notify();pen.wait(); } catch (InterruptedException e) {e.printStackTrace(); } }System.out.println(String.format("%s Wait over again using pen",this.getName())); }}publicclassWaitNotifyExample1 {publicstaticvoidmain(String[] args) {Pen pen =newPen();Thread st1 =newThread(new Studentt(pen));Thread st2 =newThread(new Studentt(pen));st1.start();st2.start();pen.notify(); }}//------------Exception in thread "main"java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at com.gs.corejava.datastructures.WaitNotifyExample1.main(WaitNotifyExample1.java:40)Thread-2Doing some work with pen Thread-0Doing some work with pen Thread-2Going to wait for pen Thread-0Going to wait for pen Thread-2Wait over again using penInfiniteWaitingfor Thread-0 as no onw to wake up//---Ex:5---packagecom.gs.corejava.datastructures;classPen {}classStudenttextendsThread {Pen pen;publicStudentt(Pen pen) {this.pen= pen; } @Overridepublicvoidrun() {System.out.println(String.format("%s Doing some work with pen ",this.getName()));System.out.println(String.format("%s Going to wait for pen ",this.getName()));synchronized (pen) {try {pen.notify();pen.wait(); } catch (InterruptedException e) {e.printStackTrace(); } }System.out.println(String.format("%s Wait over again using pen",this.getName())); }}publicclassWaitNotifyExample1 {publicstaticvoidmain(String[] args) {Pen pen =newPen();Thread st1 =newThread(new Studentt(pen));Thread st2 =newThread(new Studentt(pen));st1.start();st2.start();synchronized (pen) {pen.notify(); } }}//------------Thread-2Doing some work with pen Thread-0Doing some work with pen Thread-2Going to wait for pen Thread-0Going to wait for pen Thread-2Wait over again using penInfiniteWaitingfor Thread-0 as no onw to wake up//------------ //---Ex:6---packagecom.gs.corejava.datastructures;classPen {}classStudenttextendsThread {Pen pen;publicStudentt(Pen pen) {this.pen= pen; } @Overridepublicvoidrun() {System.out.println(String.format("%s Doing some work with pen ",this.getName()));System.out.println(String.format("%s Going to wait for pen ",this.getName()));synchronized (pen) {try {pen.notify();pen.wait(); } catch (InterruptedException e) {e.printStackTrace(); } }System.out.println(String.format("%s Wait over again using pen",this.getName())); }}publicclassWaitNotifyExample1 {publicstaticvoidmain(String[] args) {Pen pen =newPen();Thread st1 =newThread(new Studentt(pen));Thread st2 =newThread(new Studentt(pen));st1.start();st2.start();try {Thread.sleep(1000); } catch (InterruptedException e) {e.printStackTrace(); }synchronized (pen) {pen.notify(); } }}//------------Thread-0Doing some work with pen Thread-2Doing some work with pen Thread-0Going to wait for pen Thread-2Going to wait for pen Thread-0Wait over again using penThread-2Wait over again using pen//------------
integer from Thread-0::0
integer from Thread-1::1
integer from Thread-0::2
integer from Thread-1::3
integer from Thread-0::4
integer from Thread-1::5
integer from Thread-0::6
integer from Thread-1::7
integer from Thread-0::8
integer from Thread-1::9