Java examples for Thread:Producer Consumer
Two threads manipulating a synchronized buffer.
import java.security.SecureRandom; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Consumer implements Runnable { private static final SecureRandom generator = new SecureRandom(); private final Buffer sharedLocation; // reference to shared object public Consumer(Buffer sharedLocation) { this.sharedLocation = sharedLocation; }// w ww . ja va2 s. com public void run() { int sum = 0; for (int count = 1; count <= 10; count++) { // sleep 0 to 3 seconds, read value from buffer and add to sum try { Thread.sleep(generator.nextInt(3000)); sum += sharedLocation.blockingGet(); } catch (InterruptedException exception) { Thread.currentThread().interrupt(); } } System.out.printf("%n%s %d%n%s%n", "Consumer read values totaling", sum, "Terminating Consumer"); } } class Producer implements Runnable { private static final SecureRandom generator = new SecureRandom(); private final Buffer sharedLocation; // reference to shared object public Producer(Buffer sharedLocation) { this.sharedLocation = sharedLocation; } // store values from 1 to 10 in sharedLocation public void run() { int sum = 0; for (int count = 1; count <= 10; count++) { try // sleep 0 to 3 seconds, then place value in Buffer { Thread.sleep(generator.nextInt(3000)); // random sleep sharedLocation.blockingPut(count); // set value in buffer sum += count; // increment sum of values } catch (InterruptedException exception) { Thread.currentThread().interrupt(); } } System.out.printf("Producer done producing%nTerminating Producer%n"); } } class SynchronizedBuffer implements Buffer { private final Lock accessLock = new ReentrantLock(); // conditions to control reading and writing private final Condition canWrite = accessLock.newCondition(); private final Condition canRead = accessLock.newCondition(); private int buffer = -1; // shared by producer and consumer threads private boolean occupied = false; // whether buffer is occupied public void blockingPut(int value) throws InterruptedException { accessLock.lock(); // lock this object // output thread information and buffer information, then wait try { // while buffer is not empty, place thread in waiting state while (occupied) { System.out.println("Producer tries to write."); displayState("Buffer full. Producer waits."); canWrite.await();// wait until buffer is empty } buffer = value; // set new buffer value // indicate producer cannot store another value // until consumer retrieves current buffer value occupied = true; displayState("Producer writes " + buffer); // signal any threads waiting to read from buffer canRead.signalAll(); } finally { accessLock.unlock(); // unlock this object } } public int blockingGet() throws InterruptedException { int readValue = 0; // initialize value read from buffer accessLock.lock(); // lock this object // output thread information and buffer information, then wait try { // if there is no data to read, place thread in waiting state while (!occupied) { System.out.println("Consumer tries to read."); displayState("Buffer empty. Consumer waits."); canRead.await(); // wait until buffer is full } occupied = false; readValue = buffer; // retrieve value from buffer displayState("Consumer reads " + readValue); canWrite.signalAll(); } finally { accessLock.unlock(); // unlock this object } return readValue; } private void displayState(String operation) { try { accessLock.lock(); // lock this object System.out.printf("%-40s%d\t\t%b%n%n", operation, buffer, occupied); } finally { accessLock.unlock(); // unlock this object } } } interface Buffer { public void blockingPut(int value) throws InterruptedException; public int blockingGet() throws InterruptedException; } public class Main { public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); Buffer sharedLocation = new SynchronizedBuffer(); System.out.printf("%-40s%s\t\t%s%n%-40s%s%n%n", "Operation", "Buffer", "Occupied", "---------", "------\t\t--------"); // execute the Producer and Consumer tasks executorService.execute(new Producer(sharedLocation)); executorService.execute(new Consumer(sharedLocation)); executorService.shutdown(); executorService.awaitTermination(1, TimeUnit.MINUTES); } }