Below are the conditions for producer consumer pattern. We need to ensure that the thread should not be blocked either if the buffer is empty or full. This is achieved by calling wait() and notify() method on the lock object which is used to synchronized the block of code. Please note that it is important for both threads to synchronize on the same monitor / lock object.
Note: wait() and notify() should not be called outside the synchronized code block
Below is the example code :
package com.refermynotes;
public class ProducerConsumerExample {
public static int[] buffer;
public static Object lock = new Object();
public static int count;
static class Producer{
public void produce(){
synchronized (lock) {
if(isFull(buffer)){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced: "+count);
buffer[count++] = 1;
lock.notifyAll();
}
}
}
static class Consumer{
public void consume(){
synchronized(lock){
if(isEmpty()){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffer[--count] = 0;
System.out.println("Consumed: "+count);
lock.notifyAll();
}
}
}
private static boolean isEmpty() {
return count == 0;
}
private static boolean isFull(int[] buffer) {
return count == buffer.length;
}
public static void main(String[] args) {
buffer = new int[50];
count = 0;
final Producer p = new Producer();
final Consumer c = new Consumer();
Runnable producerTask = new Runnable() {
@Override
public void run() {
for(int i =0; i<100 font="" i="">100>
p.produce();
}
System.out.println("Done Producing");
}
};
Runnable consumerTask = new Runnable() {
@Override
public void run() {
for(int i =0; i<100 font="" i="">100>
c.consume();
}
System.out.println("Done Consuming");
}
};
Thread producerThread = new Thread(producerTask);
Thread consumerThread = new Thread(consumerTask);
producerThread.start();
consumerThread.start();
try {
producerThread.join();
consumerThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Remaining :"+count);
}
}
- A producer produces values inside a buffer.
- A consumer consumes the values from this buffer.
- The buffer can be empty or full.
- Producer and consumer runs in their own thread.
Note: wait() and notify() should not be called outside the synchronized code block
Below is the example code :
package com.refermynotes;
public class ProducerConsumerExample {
public static int[] buffer;
public static Object lock = new Object();
public static int count;
static class Producer{
public void produce(){
synchronized (lock) {
if(isFull(buffer)){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced: "+count);
buffer[count++] = 1;
lock.notifyAll();
}
}
}
static class Consumer{
public void consume(){
synchronized(lock){
if(isEmpty()){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffer[--count] = 0;
System.out.println("Consumed: "+count);
lock.notifyAll();
}
}
}
private static boolean isEmpty() {
return count == 0;
}
private static boolean isFull(int[] buffer) {
return count == buffer.length;
}
public static void main(String[] args) {
buffer = new int[50];
count = 0;
final Producer p = new Producer();
final Consumer c = new Consumer();
Runnable producerTask = new Runnable() {
@Override
public void run() {
for(int i =0; i<100 font="" i="">100>
p.produce();
}
System.out.println("Done Producing");
}
};
Runnable consumerTask = new Runnable() {
@Override
public void run() {
for(int i =0; i<100 font="" i="">100>
c.consume();
}
System.out.println("Done Consuming");
}
};
Thread producerThread = new Thread(producerTask);
Thread consumerThread = new Thread(consumerTask);
producerThread.start();
consumerThread.start();
try {
producerThread.join();
consumerThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Remaining :"+count);
}
}
Comments
Post a Comment