import java.util.*; // this version is a slight improvement in that a Producer is not allowed to produce once rear == 10. This is // not a good solution because the buffer may not be full and yet we are still shutting down the Producer. We // want to use a circular array for our buffer to fix this (see the next program). Once rear and front are 10, // we stop the entire run by setting done to true. public class ProducerConsumer3 { private static int[] buffer; private static int front, rear; private static Random g; private static Thread t1, t2, t3, t4, t5; private static boolean done; public static void main(String[] args) { buffer=new int[10]; front=0; rear=0; g=new Random(); done=false; Producer p1=new Producer("Producer 1"); Producer p2=new Producer("Producer 2"); Consumer c1=new Consumer("Consumer 1"); Consumer c2=new Consumer("Consumer 2"); Consumer c3=new Consumer("Consumer 3"); t1=new Thread(p1); t2=new Thread(p2); t3=new Thread(c1); t4=new Thread(c2); t5=new Thread(c3); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } public static class Producer implements Runnable { private String name; public Producer(String name){ this.name=name; } public void run() { int temp; while(!done) { try{ temp=g.nextInt(1000); System.out.println(name + " sleeping for " + temp); Thread.sleep(temp); } catch(InterruptedException e) { System.out.println(e); } if(rear>9) { // cannot produce any more, would cause an Exception System.out.println("Producer " + name + " cannot produce, buffer full"); } else { // otherwise, room to produce so do so temp=g.nextInt(10)+1; System.out.println("Producer " + name + " producing " + temp + " at " + rear); buffer[rear]=temp; rear++; } } } } public static class Consumer implements Runnable { private String name; public Consumer(String name){ this.name=name; } public void run() { int temp; while(!done) { try{ temp=g.nextInt(1000); System.out.println(name + " sleeping for " + temp); Thread.sleep(temp); } catch(InterruptedException e) { System.out.println(e); } while(front>=rear) { System.out.println(name + " attempting to consume empty list, forced to wait"); try{ if(g.nextInt(2)==1) t1.join(); else t2.join(); // this approach still has a flaw - once a consumer joins a producer, } // it waits until the producer terminates, but this may not happen unless // one consumer reaches the if statement below to set done to true! catch(InterruptedException e) { System.out.println(e); } } if(front==10&&rear==10) // stop the run once the buffer cannot be used any more { System.out.println("Cannot continue, buffer empty but no room left over"); done=true; } else { temp=buffer[front]; System.out.println("Consumer " + name + " consuming " + temp + " at " + front); front++; } } } } } // run this version and we won't have the earlier problems but we can either run out of buffer space since // we are not using a circular queue or get stuck with producers attempting to produce into a full queue // indefinitely!