import java.io.*; public class ProducerConsumer { Object value; Object lockEmpty = new Object(); Object lockFull = new Object(); volatile boolean valueReady; public void produce (Object o) { // we don't want to write a new value until the old value has // been consumed synchronized (lockEmpty) { while (valueReady) { try { lockEmpty.wait(); } catch (InterruptedException e) {} } value = o; valueReady = true; } synchronized (lockFull) { lockFull.notifyAll(); } } public Object consume () { // we can't read a value until a producer puts one there. Object o; synchronized (lockFull) { while (!valueReady) { try { lockFull.wait(); } catch (InterruptedException e) {} } o = value; value = null; valueReady = false; } synchronized (lockEmpty) { lockEmpty.notifyAll(); } return o; } public static void main (String[] args) { final ProducerConsumer p = new ProducerConsumer(); int numProducers = 1; int numConsumers = 1; // figure out how many producers and consumers to use if (args.length == 2) { numProducers = Integer.parseInt(args[0]); numConsumers = Integer.parseInt(args[1]); } // example of an "inner class" for creating threads. for (int i = 0; i " + p.consume()); try { Thread.sleep(500); } catch (InterruptedException e) { return; } } } }).start(); } }