We have the some ways to communicate in between threads.
All of usknow that "wait" and "notify", which is a traditional method of communicating.
With the introduction of Locks and Condition , we have better performance and control .
It was already proved that Locks and Conditions are more throughput than Synchronized blocks.
Here I will try to explain the simple producer - consumer problem without Locks and Condition.
package org.ohms.threads.locks; import java.util.Random; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * Producer Consumer Problem...Solved with Locks * * @author * */ public class PCproblemWithLocks { private static int storedBox=-1;; public static void main(String[] args) throws InterruptedException { int totalProduction=1000; Lock lock=new ReentrantLock(); Condition condition= lock.newCondition(); Buffer buffer= new Buffer(); Thread producer= new Thread(new Producer(totalProduction, buffer,lock,condition)); Thread consumer= new Thread(new Consumer(totalProduction, buffer,lock,condition)); System.out.println("====================================="); producer.start(); consumer.start(); producer.join(); consumer.join(); System.out.println("Completed ....."); } /** * used to store the values or a common * object where two threads used. * * @author * */ static class Buffer { void put(int newValue) { storedBox = newValue; } int get() { return storedBox; } void clear() { storedBox=-1; } } /** * Used to store the Value * in the StoredBox(int variable defined above) * * @author * */ static class Producer implements Runnable { private int counter; private Buffer buffer; private Lock lock; private Condition condition; public Producer(int count,Buffer buffer,Lock lock,Condition condition) { this.counter=count; this.buffer=buffer; this.lock=lock; this.condition=condition; System.out.println("Producer Started placing the Values"); } @Override public void run() { try { this.lock.lock(); System.out.println(" Producer Lock Acquired "); for (int i = 0; i < this.counter; i++) { if(this.buffer.get()!=-1) { //System.out.println("Waiting to put>>>>>>"); condition.await(); System.out.println(" Producer Lock Acquired "); } int randomValue=i;//new Random().nextInt(100); this.buffer.put(randomValue); System.out.println("Produced -->"+randomValue); condition.signalAll(); System.out.println(" Producer Lock Released "); } } catch (InterruptedException e) { e.printStackTrace(); }finally{ this.lock.unlock(); } } } /** * used to retrieve/read the stored value * in the StoredValue Box * * @author Kumar * */ static class Consumer implements Runnable { private int counter; private Buffer buffer; private Lock lock; private Condition condition; public Consumer(int count,Buffer buffer,Lock lock,Condition condition) { this.counter=count; this.buffer=buffer; this.lock=lock; this.condition=condition; System.out.println("Consumer started Reading the Values "); } @Override public void run() { this.lock.lock(); System.out.println(" Consumer Lock Acquired "); try { for (int i = 0; i < this.counter; i++) { if(this.buffer.get()==-1) { //System.out.println("Waiting to get <<<<<<<<<<"); condition.await(); System.out.println(" Consumer Lock Acquired "); } System.out.println("Consumed -->"+this.buffer.get()); this.buffer.clear(); condition.signalAll(); System.out.println(" Consumer Lock Released "); } } catch (InterruptedException e) { e.printStackTrace(); }finally{ this.lock.unlock(); } } } }run the above program to know the usage of the Locks and condition in java .