Using Lock and condition to solve producer consumer problem

Producer consumer problem is an age old case study which every second interviewer asks. Its about sharing common resource between multiple threads where one thread can be a producer of some data and other threads can be consumers of that data. Previously we used to solve it using Synchronization, notify, notifyall,wait apis but now the trend has changed and better apis are available in Java.

You can read how reentrant lock technique is better than synchronizing the block of code :
How is reentrant lock better than Synchronization

In this code we have created a custom blocking queue which has two methods get() and put(). Get method will wait on notEmptyCondition condition if queue is empty. put method will wait on notFullCondition condition if queue is full. We have also created two threads, consumer and producer. Producer will try to put some data and consumer will try to consume that data.

package threads;
 
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
public class ProducerConsumerExample {
 
	public static void main(String[] args) {
		CustomBlockingQueue cbq = new CustomBlockingQueue();
		new Consumer(cbq).start();
		new Producer(cbq).start();
 
	}
 
}
 
 
class CustomBlockingQueue {
	Queue<String> list = new LinkedList<String>();
	Lock lock = new ReentrantLock();
	Condition notFullCondition = lock.newCondition();
	Condition notEmptyCondition = lock.newCondition();
	private static final int CAPACITY = 2;
 
	public void put(String value) {
		lock.lock();
		if (list.size() == CAPACITY) {
			System.out.println(Thread.currentThread().getName() + " - List is full. Lets wait");
 
			try {
				notFullCondition.await();
				System.out.println(Thread.currentThread().getName() + " - List is not full now");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
 
		list.add(value);
		System.out.println(Thread.currentThread().getName() + " - Added value to list - " + value);	
		notEmptyCondition.signalAll();
 
		lock.unlock();
	}
 
	public String get() {
		lock.lock();
		if (list.size() == 0) {
			System.out.println(Thread.currentThread().getName() + " - List is empty. Lets wait");
			try {
				notEmptyCondition.await();
				System.out.println(Thread.currentThread().getName() + " - List has some value now");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		String result = list.poll();
		System.out.println(Thread.currentThread().getName() + " - Got value from list - " + result);
 
		notFullCondition.signalAll();
		lock.unlock();
		return result;
 
	}
}
 
 
class Producer extends Thread {
 
	CustomBlockingQueue cbq = null;
 
	public Producer(CustomBlockingQueue cbq) {
		this.cbq = cbq;
	}
 
	@Override
	public void run() {
		cbq.put("hello");
		cbq.put("uday");
		cbq.put("ogra");
 
	}
 
}
 
class Consumer extends Thread {
 
	CustomBlockingQueue cbq = null;
 
	public Consumer(CustomBlockingQueue cbq) {
		this.cbq = cbq;
	}
 
	@Override
	public void run() {
		cbq.get();
 
	}
 
}

Running this code will produce multiple results like these :

Thread-0 – List is empty. Lets wait
Thread-1 – Added value to list – hello
Thread-1 – Added value to list – uday
Thread-0 – List has some value now
Thread-0 – Got value from list – hello
Thread-1 – Added value to list – ogra

Thread-0 – List is empty. Lets wait
Thread-1 – Added value to list – hello
Thread-0 – List has some value now
Thread-0 – Got value from list – hello
Thread-1 – Added value to list – uday
Thread-1 – Added value to list – ogra

Thread-0 – List is empty. Lets wait
Thread-1 – Added value to list – hello
Thread-1 – Added value to list – uday
Thread-1 – List is full. Lets wait
Thread-0 – List has some value now
Thread-0 – Got value from list – hello
Thread-1 – List is not full now
Thread-1 – Added value to list – ogra

Uday Ogra

Connect with me at http://facebook.com/tendulkarogra and lets have some healthy discussion :)

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *