class Q ... { int n; boolean valueSet = false; synchronized int get()...{ if(!valueSet)...{ try ...{ wait(); } catch (InterruptedException e) ...{ e.printStackTrace(); } } System.out.println("Got:" + n); valueSet = false; notify(); return n; } synchronized void put(int n)...{ if(valueSet)...{ try ...{ wait(); } catch (InterruptedException e) ...{ e.printStackTrace(); } } this.n=n; System.out.println("Put:" + n); valueSet = true; notify(); }} class Producer implements Runnable ... { Q q; Thread t; Producer(Q q)...{ this.q=q; t = new Thread(this,"Producer"); t.start(); } public void run()...{ int i=0; while(true)...{ q.put(i++); } } public void stop()...{ t.stop(); }} class Consumer implements Runnable ... { Q q; Thread t; Consumer(Q q)...{ this.q=q; t=new Thread(this,"Consumer"); t.start(); } public void run()...{ int i=0; while(true)...{ q.get(); } } public void stop()...{ t.stop(); }} class PC ... { public static void main(String args[])...{ Q q=new Q(); Consumer c = new Consumer(q); Producer p = new Producer(q); try ...{ Thread.sleep(100); } catch (InterruptedException e) ...{ e.printStackTrace(); } p.stop(); c.stop(); try ...{ p.t.join(); c.t.join(); } catch (InterruptedException e1) ...{ e1.printStackTrace(); } }}