Java examples for Thread:Producer Consumer
Two threads correctly manipulating a synchronized buffer.
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.security.SecureRandom; class Consumer implements Runnable { private static final SecureRandom generator = new SecureRandom(); private final Buffer sharedLocation; // reference to shared object public Consumer(Buffer sharedLocation) {//from w ww . j av a 2s.c o m this.sharedLocation = sharedLocation; } // read sharedLocation's value 10 times and sum the values 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"); } } interface Buffer { public void blockingPut(int value) throws InterruptedException; public int blockingGet() throws InterruptedException; } class SynchronizedBuffer implements Buffer { private int buffer = -1; // shared by producer and consumer threads private boolean occupied = false; public synchronized void blockingPut(int value) throws InterruptedException { // while there are no empty locations, place thread in waiting state while (occupied) { System.out.println("Producer tries to write."); // for demo only displayState("Buffer full. Producer waits."); // for demo only wait(); } buffer = value; // set new buffer value occupied = true; displayState("Producer writes " + buffer); // for demo only notifyAll(); // tell waiting thread(s) to enter runnable state } public synchronized int blockingGet() throws InterruptedException { while (!occupied) { System.out.println("Consumer tries to read."); // for demo only displayState("Buffer empty. Consumer waits."); // for demo only wait(); } occupied = false; displayState("Consumer reads " + buffer); // for demo only notifyAll(); // tell waiting thread(s) to enter runnable state return buffer; } private synchronized void displayState(String operation) { System.out.printf("%-40s%d\t\t%b%n%n", operation, buffer, occupied); } } 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"); } } 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--------"); executorService.execute(new Producer(sharedLocation)); executorService.execute(new Consumer(sharedLocation)); executorService.shutdown(); executorService.awaitTermination(1, TimeUnit.MINUTES); } }