/* This version does not work because when a thread invokes notify, the other thread might not be in a wait state. Thus, a deadlock could occur when a thread calls wait after its notify has been invoked. To solve this situation, a call to notify needs to be remembered. This is achieved with the class Semaphore shown at http://profesores.elo.utfsm.cl/~agv/elo330/2s19/lectures/JavaThreads/JavaThreads.html. */ import java.io.*; public class PandC_fullAndemptyVersion_DoesNotWork { static int produceSpeed = 200; static int consumeSpeed = 200; public static void main (String args[]) { if (args.length > 0) produceSpeed = Integer.parseInt (args[0]); if (args.length > 1) consumeSpeed = Integer.parseInt (args[1]); Monitor monitor = new Monitor(); String emptyLock = ""; String fullLock = ""; new Producer(monitor, produceSpeed, emptyLock, fullLock); new Consumer(monitor, consumeSpeed, emptyLock, fullLock); try { Thread.sleep(10000); } catch (InterruptedException e) { } System.exit(0); } } class Monitor { PrintWriter out = new PrintWriter (System.out, true); int token; int get () { out.println ("Got: " + token); return token; } //set token value void set (int value) { token = value; out.println ("Set: " + token); } } class Producer implements Runnable { Monitor monitor; int speed; String emptyLock, fullLock; Producer (Monitor monitor, int speed, String emptyLock, String fullLock) { this.monitor = monitor; this.speed = speed; this.emptyLock = emptyLock; this.fullLock = fullLock; new Thread (this, "Producer").start(); } public void run() { int i = 0; while (true) { monitor.set (i++); try { synchronized(fullLock) { fullLock.notify(); } Thread.sleep ((int) (Math.random() * speed)); synchronized(emptyLock) { emptyLock.wait(); } } catch (InterruptedException e) { } } } } class Consumer implements Runnable { Monitor monitor; int speed; String emptyLock, fullLock; Consumer (Monitor monitor, int speed, String emptyLock, String fullLock) { this.monitor = monitor; this.speed = speed; this.emptyLock = emptyLock; this.fullLock = fullLock; new Thread (this, "Consumer").start(); } public void run() { while (true) { try { Thread.sleep ((int) (Math.random() * speed)); synchronized(fullLock) { fullLock.wait(); } monitor.get(); synchronized(emptyLock) { emptyLock.notify(); } } catch (InterruptedException e) { } } } }