// Purpose. Producer & consumer threads, 1 Monitor [Source: Roberts, p212] class Mailbox { private boolean request; private String message; public Mailbox() { request = false; } public synchronized void storeMessage( String msg ) { while (request == true) { // no room for another message try { wait(); } catch (InterruptedException e ) { } } request = true; message = msg; notifyAll(); } public synchronized String retrieveMessage() { while (request == false) { // no message to retrieve try { wait(); } catch (InterruptedException e ) { } } request = false; notifyAll(); return message; } } class ProducerThread extends Thread { private Mailbox mb; private int id; private static int num = 1; public ProducerThread( Mailbox m ) { mb = m; id = num++; } public void run() { for (int i=0; i < 9; i++) { System.out.println( "sending " + i + " from thread " + id ); mb.storeMessage( "message " + i + " from thread " + id ); } for (int i=0; i < 3; i++) { System.out.println( "sending DONE" ); mb.storeMessage( "DONE" ); } System.out.println( "%%% thread " + id + " exiting" ); } } class ConsumerThread extends Thread { private Mailbox mb; private int id; private static int num = 2; public ConsumerThread( Mailbox m ) { mb = m; id = num++; } public void run() { while (true) { String str = mb.retrieveMessage(); if (str.equals( "DONE" )) break; System.out.println( " thread " + id + " received --- " + str ); } System.out.println( "%%% thread " + id + " exiting" ); } } class ThreadMailbox { public static void main( String[] args ) { Mailbox mb = new Mailbox(); new ProducerThread( mb ).start(); new ConsumerThread( mb ).start(); new ConsumerThread( mb ).start(); new ConsumerThread( mb ).start(); } } // sending 0 from thread 1 // sending 1 from thread 1 // thread 4 received --- message 0 from thread 1 // sending 2 from thread 1 // thread 2 received --- message 1 from thread 1 // sending 3 from thread 1 // thread 3 received --- message 2 from thread 1 // sending 4 from thread 1 // thread 4 received --- message 3 from thread 1 // sending 5 from thread 1 // thread 2 received --- message 4 from thread 1 // sending 6 from thread 1 // thread 3 received --- message 5 from thread 1 // sending 7 from thread 1 // thread 4 received --- message 6 from thread 1 // sending 8 from thread 1 // thread 2 received --- message 7 from thread 1 // sending DONE // thread 3 received --- message 8 from thread 1 // sending DONE // %%% thread 4 exiting // sending DONE // %%% thread 2 exiting // %%% thread 1 exiting // %%% thread 3 exiting