Select Page
Thread Communication in Java

Written by Buddhi

2020-05-12

Interthread communication in Java

package org.example;

public class ThreadCommunication {
private static final int DATA_SIZE = 1000;

public static void main(String[] args) {
//common channel for producing and consuming data
Channel channel = new Channel();

Producer producer = new Producer(channel, DATA_SIZE);
Consumer consumer = new Consumer(channel, DATA_SIZE);

Thread producerThread = new Thread(producer);
Thread consumerThread = new Thread(consumer);

producerThread.start();
consumerThread.start();
}
}

/**
* Carry the data produced by producer to be consumed by consumer
*/
class Channel {

private int data;
private boolean hasData;

/**
* Produce data and notify the consumer for consumption.
* Halt production if data is not consumed.
* @param value data produced
*/
public synchronized void produceData(int value) {
//when there is data already produced and exists in pipeline
//wait for the consumer to consume data. don't produce anymore data
while (hasData) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

data = value;
hasData = true;
System.out.println("Produced data: " + data);
//notify the consumer (waiting threads) to consume the data
notify();
}

/**
* Consume data and notify producer to produce more data, wait if no data exists
* @return produced data
*/
public synchronized int consumeData() {
//when no data in pipeline, wait for producer to produce more data
while (!hasData) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
hasData = false;
System.out.println("Sent for consumption: " + data);
notify(); //notify the producer to produce more data
return data;
}
}

/**
* Produce more data to be produced by producer
*/
class Producer implements Runnable {
private final Channel channel;
private final int dataSize;

public Producer(Channel c, int dataSize) {
this.channel = c;
this.dataSize = dataSize;
}

@Override
public void run() {
for (int i = 0; i < dataSize; i++) {
channel.produceData(i);
}
}
}

/**
* Consume the data produced by producer
*/
class Consumer implements Runnable {

private final Channel channel;
private final int dataSize;

public Consumer(Channel channel, int dataSize) {
this.channel = channel;
this.dataSize = dataSize;
}

@Override
public void run() {
for (int i = 0; i < dataSize; i++) {
int receivedData = channel.consumeData();
System.out.println("Consumed data: " + receivedData);
}
}
}

Related Articles

Dependency Injection Summary

Dependency Injection Summary

Summary of dependency injection in Spring Boot. All the necessary dependencies are handed over to the object by spring. It frees the object from resolving the dependencies. It greatly simplifies the code and improves code reusability. It promotes programming to...

Spring Annotations and Component Scanning

Spring Annotations and Component Scanning

Best practices for defining components and scanning them Annotate the class by including the exact place where to scan for components with @ComponentScan({"com.app.service"," com.app.repo"}) rather than providing a path like @ComponentScan("com") or...

Various description of Big O – Time complexity algorithms

Various description of Big O – Time complexity algorithms

Understanding the time complexity of Big O and log. O(log N) means time goes up linearly while the n goes up exponentially. So if it takes 1 second to compute 10 elements, it will take 2 seconds to compute 100 elements, 3 seconds to compute 1000 elements, and so on....