1
INTER-THREAD COMMUNICATION IN JAVA
Inter-thread communication in Java is a technique through which multiple threads communicate
with each other. It provides an efficient way through which more than one thread communicate
with each other by reducing CPU idle time. CPU idle time is a process in which CPU cycles are
not wasted.
When more than one threads are executing simultaneously, sometimes they need to communicate
with each other by exchanging information with each other. A thread exchanges information before
or after it changes its state.
There are several situations where communication between threads is important. For example,
suppose that there are two threads A and B. Thread B uses data produced by Thread A and performs
its task.
If Thread B waits for Thread A to produce data, it will waste many CPU cycles. But if threads A
and B communicate with each other when they have completed their tasks, they do not have to
wait and check each other’s status every time.
Thus, CPU cycles will not waste. This type of information exchanging between threads is called
inter thread communication in Java.
How to Achieve Inter Thread Communication in Java
Inter thread communication in Java can be achieved by using three methods provided by Object
class of java.lang package. They are:
1. wait()
2. notify()
3. notifyAll()
These methods can be called only from within a synchronized method or synchronized block of
code otherwise, an exception named IllegalMonitorStateException is thrown.
All these methods are declared as final. Since it throws a checked exception, therefore, you must
be used these methods within Java try-catch block.
wait() Method in Java
wait() method in Java notifies the current thread to give up the monitor (lock) and to go into sleep
state until another thread wakes it up by calling notify() method. This method throws
InterruptedException.
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
2
Various forms of wait() method allow us to specify the amount of time a thread can wait. They are
as follows:
• public final void wait()
• public final void wait(long millisecond) throws InterruptedException
• public final void wait(long millisecond, long nanosecond) throws
InterruptedException
All overloaded forms of wait() method throw InterruptedException. If time is specified in the
wait() method, a thread can wait for maximum time.
Note:
1. A monitor is an object which acts as a lock. It is applied to a thread only when it is inside a
synchronized method.
2. Only one thread can use monitor at a time. When a thread acquires a lock, it enters the monitor.
3. When a thread enters into the monitor, other threads will wait until first thread exits monitor.
4. A lock can have any number of associated conditions.
notify() Method in Java
The notify() method wakes up a single thread that called wait() method on the same object. If more
than one thread is waiting, this method will awake one of them. The general syntax to call notify()
method is as follows:
public final void notify()
notifyAll() Method in Java
The notifyAll() method is used to wake up all threads that called wait() method on the same object.
The thread having the highest priority will run first. The general syntax to call notifyAll() method
is as follows:
public final void notifyAll()
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
3
PRODUCER-CONSUMER PROGRAM IN JAVA(METHOD-I)-(WEEK-7)
The Producer-Consumer problem is a synchronization problem where two threads, the producer
and the consumer, share a common, fixed-size buffer. The producer's role is to produce data and
add it to the buffer, while the consumer's role is to consume the data from the buffer. The
producer is responsible for producing an item and adding it to the buffer or list. The consumer is
responsible for consuming an item by removing it from the list. The producer cannot produce an
item if the list is already full, and the consumer cannot consume an item if the list is empty. This
problem is also known as a bounded-buffer problem(Race-Condition Problem).
class ItemQueue {
int item;
boolean valueSet = false;
synchronized int getItem()
while (!valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
System.out.println("Consummed:" + item);
valueSet = false;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
4
notify();
return item;
synchronized void putItem(int item) {
while (valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
this.item = item;
valueSet = true;
System.out.println("Produced: " + item);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
notify();
class Producer implements Runnable{
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
5
ItemQueue itemQueue;
Producer(ItemQueue itemQueue){
this.itemQueue = itemQueue;
new Thread(this, "Producer").start();
public void run() {
int i = 0;
while(true) {
itemQueue.putItem(i++);
class Consumer implements Runnable{
ItemQueue itemQueue;
Consumer(ItemQueue itemQueue){
this.itemQueue = itemQueue;
new Thread(this, "Consumer").start();
public void run() {
while(true) {
itemQueue.getItem();
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
6
class ProducerConsumer{
public static void main(String args[]) {
ItemQueue itemQueue = new ItemQueue();
new Producer(itemQueue);
new Consumer(itemQueue);
OUTPUT
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
7
PRODUCER-CONSUMER PROGRAM IN JAVA(METHOD-II)
Write a Java program to create a producer-consumer scenario using the wait() and notify()
methods for thread synchronization.
Solution-1:
Java Code:
// ProducerConsumer.java
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer {
private static final int BUFFER_SIZE = 5;
private static final Queue < Integer > buffer = new LinkedList < > ();
public static void main(String[] args) {
Thread producerThread = new Thread(new Producer());
Thread consumerThread = new Thread(new Consumer());
producerThread.start();
consumerThread.start();
static class Producer implements Runnable {
public void run() {
int value = 0;
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
8
while (true) {
synchronized(buffer) {
// Wait if the buffer is full
while (buffer.size() == BUFFER_SIZE) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("Producer produced: " + value);
buffer.add(value++);
// Notify the consumer that an item is produced
buffer.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
9
static class Consumer implements Runnable {
public void run() {
while (true) {
synchronized(buffer) {
// Wait if the buffer is empty
while (buffer.isEmpty()) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
int value = buffer.poll();
System.out.println("Consumer consumed: " + value);
// Notify the producer that an item is consumed
buffer.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
10
Output:
Producer produced: 0
Producer produced: 1
Consumer consumed: 0
Consumer consumed: 1
Producer produced: 2
Producer produced: 3
Producer produced: 4
Producer produced: 5
Producer produced: 6
Consumer consumed: 2
Consumer consumed: 3
Consumer consumed: 4
Consumer consumed: 5
Consumer consumed: 6
Producer produced: 7
Producer produced: 8
Producer produced: 9
Producer produced: 10
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
11
Producer produced: 11
...................................
...................................
Explanation:
In the above exercise -
• The "Producer" class implements the Runnable interface and represents the producer
thread. It continuously produces items by adding values to the shared buffer. When the
buffer is full, the producer waits until the consumer consumes an item and notifies it.
• The "Consumer" class also implements the Runnable interface and represents the
consumer thread. It continuously consumes items by removing values from the shared
buffer. As soon as the buffer is empty, the consumer uses the wait() method to wait until a
new item is produced by the producer.
• In the main() method, we create instances of the Producer and Consumer classes as
separate threads and start them concurrently.
Flowchart:
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
12
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
13
Solution-2:
The code we provided above has a potential issue with deadlock, and using notifyAll() is a good
solution to avoid it. Here's an updated version of the above code with notifyAll():
Java Code:
// ProducerConsumer.java
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
14
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer {
private static final int BUFFER_SIZE = 5;
private static final Queue<Integer> buffer = new LinkedList<>();
public static void main(String[] args) {
// Create producer and consumer threads
Thread producerThread = new Thread(new Producer());
Thread consumerThread = new Thread(new Consumer());
// Start producer and consumer threads
producerThread.start();
consumerThread.start();
// Producer thread class
static class Producer implements Runnable {
public void run() {
int value = 0;
while (true) {
synchronized (buffer) {
// Wait if the buffer is full
while (buffer.size() == BUFFER_SIZE) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
15
// Produce item and add to the buffer
System.out.println("Producer produced: " + value);
buffer.add(value++);
// Notify all consumers that an item is produced
buffer.notifyAll();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
// Consumer thread class
static class Consumer implements Runnable {
public void run() {
while (true) {
synchronized (buffer) {
// Wait if the buffer is empty
while (buffer.isEmpty()) {
try {
buffer.wait();
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
16
} catch (InterruptedException e) {
e.printStackTrace();
// Consume item from the buffer
int value = buffer.poll();
System.out.println("Consumer consumed: " + value);
// Notify all producers that an item is consumed
buffer.notifyAll();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Output:
Producer produced: 0
Producer produced: 1
Producer produced: 2
Producer produced: 3
Producer produced: 4
PRODUCER-CONSUMER PROGRAM K.PRATHIMA
17
Consumer consumed: 0
Consumer consumed: 1
Consumer consumed: 2
Consumer consumed: 3
Consumer consumed: 4
Producer produced: 5
Producer produced: 6
Producer produced: 7
Producer produced: 8
Producer produced: 9
Consumer consumed: 5
Consumer consumed: 6
Consumer consumed: 7
.........
.........
PRODUCER-CONSUMER PROGRAM K.PRATHIMA