Skip to main content

Inter-thread Communication in Java

Introduction to Inter-thread Communication in Java

Inter-thread communication is crucial in Multithreading, a core concept in Java. Multithreading allows simultaneous execution of two or more parts of a program to maximize CPU utilization. In this tutorial, we will delve into the concept of inter-thread communication in Java, various ways to achieve it, and its importance.

What is Inter-thread Communication?

Inter-thread communication involves two or more threads working together to achieve a common goal. In Java, threads can communicate with each other by using methods like wait(), notify(), and notifyAll().

wait(), notify() and notifyAll() Methods

Java provides the wait(), notify(), and notifyAll() methods as part of the Object class. They are used to communicate between threads in Java. Here's a brief about these methods:

  1. wait(): This method tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify().
  2. notify(): It wakes up one single thread that called wait() on the same object. It should be noted that calling notify() does not actually give up a lock on a resource.
  3. notifyAll(): It wakes up all the threads that called wait() on the same object.

Synchronized Block and Inter-thread Communication

Inter-thread communication cannot exist in isolation. It needs to be coupled with the concept of synchronized blocks. Only a thread that owns a lock on an object can call wait(), notify(), and notifyAll() on it.

A synchronized block in Java is marked with the synchronized keyword. A synchronized block in Java is used to lock an object for any shared resource. When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task.

Code Example

Here is a simple example of Inter-thread communication in Java:

class Chat {
boolean flag = false;

public synchronized void Question(String msg) {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
flag = true;
notify();
}

public synchronized void Answer(String msg) {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println(msg);
flag = false;
notify();
}
}

class T1 implements Runnable {
Chat m;
String[] s1 = { "Hi", "How are you ?", "I am also doing fine!" };

public T1(Chat m1) {
this.m = m1;
new Thread(this, "Question").start();
}

public void run() {
for (int i = 0; i < s1.length; i++) {
m.Question(s1[i]);
}
}
}

class T2 implements Runnable {
Chat m;
String[] s2 = { "Hi", "I am good, what about you?", "Great!" };

public T2(Chat m2) {
this.m = m2;
new Thread(this, "Answer").start();
}

public void run() {
for (int i = 0; i < s2.length; i++) {
m.Answer(s2[i]);
}
}
}

public class TestThread {
public static void main(String[] args) {
Chat m = new Chat();
new T1(m);
new T2(m);
}
}

In the above example, two threads T1 and T2 are communicating with each other using the wait() and notify() methods.

Conclusion

In this article, we have covered inter-thread communication in Java, which is a key concept in multithreading. We learned about the wait(), notify() and notifyAll() methods and how to use them for inter-thread communication. We also saw how synchronization is necessary for these methods to work correctly. Finally, we implemented a simple chat program to showcase inter-thread communication.

Understanding these concepts is vital as they form the foundation for advanced topics in Java like thread pooling, deadlock, and starvation. Happy learning!