Google

Jul 15, 2014

Java producer consumer code example with wait and notifyAll

This simple Java multi-threaded code can be used for practicing your ability to debug concurrency issues. You will also learn the producer consumer inter thread communication in Java.



Step 1: The ProducerConsumerTest class that is runnable as a default Java main thread. Responsible for producing 2 worker threads ProducerThread and ConsumerThread.

public class ProducerConsumerTest {
 
 public static void main(String[] args) throws InterruptedException {
  
  ProducerConsumer pc = new ProducerConsumer();
  
  //spawn a new producer thread and start
  Thread producer = new Thread(new ProducerThread(pc));
  producer.start();
  
  Thread.sleep(1000); //main thread sleeps for 1 second
  
  //spawn a new consumer thread and start
  Thread consumer = new Thread(new ConsumerThread(pc));
  consumer.start();
  
 }
}



Step 2: The ProducerThread and ConsumerThread classes that run as worker threads and share The ProducerConsumer class that has the logic to produce and consume.

public class ProducerThread implements Runnable {

 private ProducerConsumer pc;

 public ProducerThread(ProducerConsumer pc) {
  this.pc = pc;
 }

 @Override
 public void run() {
  pc.produce();
 }

}


public class ConsumerThread implements Runnable {

 private ProducerConsumer pc;
  
 public ConsumerThread(ProducerConsumer pc) {
  this.pc = pc;
 }

 @Override
 public void run() {
  pc.consume();
 }

}

Step 3: Finally, the ProducerConsumer class that gets accessed by the worker threads to get th job done. The inter thread communication is done via the methods wait( ) and notifyAll( ). Both the produce( ) and consume( ) methods are synchronized as only one thread can acquire the lock to either to produce or to consume. The notify/notifyAll methods relinquishes the lock for any waiting (i.e. blocked) threads to acquire.

import java.util.concurrent.ArrayBlockingQueue;

//only one thread can access either produce or consume methods as both are synchronized
public class ProducerConsumer {

 private int count = 0;
 private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(100);
   } catch (InterruptedException ie) {}

   if (queue.isEmpty()) {
    count++;
    try {
     Thread.sleep(4000); // takes 4 secs to produce
    } catch (InterruptedException e) {}
    queue.add(count);
    System.out.println(Thread.currentThread().getName() + " produced: " + count);
    notifyAll();
   }
  }//end while
 }

 public synchronized void consume() {
  while (true) {
   try {
    wait(100);
   } catch (InterruptedException ie) {}

   if (!queue.isEmpty()) {
    Integer consumed = queue.remove(); // consumed
    System.out.println(Thread.currentThread().getName() + " consumed: " + consumed);
    notifyAll();
   }
  }//end while
 }
}


Step 4: The above program keeps running until you kill it. The output will be something like shown below every 4 seconds.

Thread-0 produced: 1
Thread-1 consumed: 1
Thread-0 produced: 2
Thread-1 consumed: 2
Thread-0 produced: 3
Thread-1 consumed: 3
Thread-0 produced: 4
Thread-1 consumed: 4
Thread-0 produced: 5
Thread-1 consumed: 5
Thread-0 produced: 6
Thread-1 consumed: 6
Thread-0 produced: 7
Thread-1 consumed: 7
//...............


In the next post will demonstrate how to debug multi-threaded applications using this code example. \

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home