Categories: Java

Inter-thread Communication in Java

What is Inter-thread Communication?

Java has a mechanism called inter-thread communication that allows another thread to enter (or lock) a paused thread’s critical section so that it can be executed.

What is polling, and what are its drawbacks?

Polling is the process of repeatedly testing a condition until it holds true. Loops are frequently used to implement polling in order to determine whether a specific condition is true or false. If it is real, a particular thing happens. Due to this, the implementation uses up a lot of CPU cycles inefficiently.

Java multi-threading approach to prevent this issue:

Java uses the wait(), notify(), and notifyAll() methods to avoid polling. All of these methods are final members of the object class, making them available to all classes. They can only be used inside a synchronized block.

  • When a different thread enters the same monitor and calls notify, wait() instructs the calling thread to release the lock and go to sleep().
  • One thread called wait() on the same object is awakened by notify(). One thing to keep in mind is that using notify() does not release a lock on a resource.
  • Notifies every thread that has called wait() on an object, using the notifyAll() function.
Difference between wait and sleep

Let’s examine the key distinctions between the wait and sleep methods.

wait()sleep()
The lock is released by the wait() method.The lock is not released by the sleep() method.
It is a method of the class Object.It is a thread class method.
Furthermore, it is the non-static methodIt is the static method
It should be notified by notify() or notifyAll() methodsAfter the specified amount of time, sleep is completed.
Example
//In this program, we will understand how to use wait and notify.
// It is the most efficient way for thread communication.
public class A 
{
 int i; 
 boolean flag = false; // flag will be true when data production is over.
synchronized void deliver(int i)
{
 if(flag)
 try
 {
  wait(); // Wait till a notification is received from Thread2. There will be no wastage of time.  
 }
 catch(InterruptedException ie)
 {
  System.out.println(ie);  
 }
   this.i = i; 
   flag = true; // When data production is over, it will store true into flag.
   System.out.println("Data Delivered: " +i);
   notify(); // When data production is over, it will notify Thread2 to use it.
 }
synchronized int receive()
{
if(!flag)
try {
 wait(); // Wait till a notification is received from Thread1. 
}
catch(InterruptedException ie){
 System.out.println(ie); 
}
 System.out.println("Data Received: " + I); 
  flag = false; // It will store false into flag when data is received.
  notify(); // When data received is over, it will notify Thread1 to produce next data.
  return i;
 }
}
public class Thread1 extends Thread
{
 A obj;
 Thread1(A obj)
 {
  this.obj = obj;
 }
public void run()
{
for(int j = 1; j <= 5; j++){
 obj.deliver(j);  
  }
}}
public class Thread2 extends Thread 
{
A obj;
Thread2(A obj)
{
 this.obj = obj;
}
public void run()
{
for(int k = 0; k <= 5; k++){
 obj.receive(); 
}
 }}
public class Communication 
{
public static void main(String[] args) 
{
 A obj = new A(); // Creating an object of class A.

// Creating two thread objects and pass reference variable obj as parameter to Thread1 and Thread2.
Thread1 t1 = new Thread1(obj);
Thread2 t2 = new Thread2(obj);
// Run both threads.
  t1.start();
  t2.start();
 }
}
Output
   Data Delivered: 1
      Data Received: 1
      Data Delivered: 2
      Data Received: 2
      Data Delivered: 3
      Data Received: 3
      Data Delivered: 4
      Data Received: 4
      Data Delivered: 5
      Data Received: 5
  1. The wait() and notify() methods are called inside the deliver() and receive() methods in this example program. Both approaches give Thread1 the ability to alert Thread2 after producing data and wait until Thread2 has finished utilizing.
  2. Similarly, Thread2 notifies Thread1 after using data and then waits until Thread1 creates and delivers the subsequent data. As a result, the output is synchronized.
  3. If the flag is set to true, Thread2 uses the data that Thread1 provided. While Thread1 is busy producing data, Thread2 periodically checks to see if the flag is true.

In the event that the flag reads false, Thread2 will wait for the object until it is notified by a notify() method.

When the data production is finished, Thread1 will immediately notify Thread2 that data is available for receipt. Thread1 and Thread2 effectively communicate with one another in this way.

Note: also read about the Synchronization in Java

Follow Me

If you like my post, please follow me to read my latest post on programming and technology.

https://www.instagram.com/coderz.py/

https://www.facebook.com/coderz.py

Share
Published by
Rabecca Fatima

Recent Posts

Generate Parenthesis | Intuition + Code | Recursion Tree | Backtracking | Java

Problem Statement: Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. Example…

3 months ago

Square Root of Integer

Given an integer A. Compute and return the square root of A. If A is…

1 year ago

Build Array From Permutation

Given a zero-based permutation nums (0-indexed), build an array ans of the same length where…

1 year ago

DSA: Heap

A heap is a specialized tree-based data structure that satisfies the heap property. It is…

2 years ago

DSA: Trie

What is a Trie in DSA? A trie, often known as a prefix tree, is…

2 years ago

Trees: Lowest Common Ancestor

What is the Lowest Common Ancestor? In a tree, the lowest common ancestor (LCA) of…

2 years ago