Step 1: ItemQueue Class
The ItemQueue class is responsible for holding the shared item and ensuring thread-safe access
using synchronized methods.
Fields:
o int item: Stores the item.
o boolean valueSet = false: A flag to check if the item is produced or consumed.
Methods:
o synchronized int getItem(): This method is called by the consumer thread to retrieve
the item.
Waits while the item is not set (valueSet == false).
Once the item is available, it consumes (retrieves) the item, sets the
valueSet flag to false, and calls notify() to wake up any waiting producer
thread.
synchronized void putItem(int item): This method is called by the
producer thread to produce an item.
Waits while the item is already set (valueSet == true).
Once it can produce, it sets the item, changes the valueSet flag to true, and
calls notify() to wake up any waiting consumer thread.
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("Consumed: " + item);
valueSet = false;
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);
notify();
Step 2: Producer Class
The Producer class implements Runnable and produces items to the ItemQueue.
Fields:
o ItemQueue queue: The shared queue object.
Constructor:
o Initializes the queue and starts the producer thread.
run() Method:
o Produces items indefinitely (in a loop), increments the item value, and sleeps for 500
milliseconds after producing each item.
class Producer implements Runnable {
ItemQueue queue;
Producer(ItemQueue queue) {
this.queue = queue;
new Thread(this, "Producer").start();
public void run() {
int i = 0;
while (true) {
queue.putItem(i++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
Step 3: Consumer Class
The Consumer class implements Runnable and consumes items from the ItemQueue.
Fields:
o ItemQueue queue: The shared queue object.
Constructor:
o Initializes the queue and starts the consumer thread.
run() Method:
o Consumes items indefinitely (in a loop) and sleeps for 500 milliseconds after
consuming each item.
class Consumer implements Runnable {
ItemQueue queue;
Consumer(ItemQueue queue) {
this.queue = queue;
new Thread(this, "Consumer").start();
public void run() {
while (true) {
queue.getItem();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
Step 4: Main Class
The ProducerConsumerExample class is the entry point of the application. It initializes the shared
ItemQueue and starts both producer and consumer threads.
public class ProducerConsumerExample {
public static void main(String[] args) {
ItemQueue queue = new ItemQueue();
new Producer(queue);
new Consumer(queue);
In summary:
1. ItemQueue: Holds and synchronizes the item.
2. Producer: Produces items.
3. Consumer: Consumes items.
4. Main: Starts the threads.
This example ensures synchronization between producer and consumer threads using Java's wait(),
notify(), and synchronized methods.