20-CS-694 Advanced Programming Techniques Spring 2012
Producer/Consumer

Interfaces, Exceptions, Graphics, Animation, Threads, Reflection, Networking, RMI, JDBC, JNI

T.java      All lectures
Solution to Midterm '99 Stream Problem

Problem:

Develop a Java class called Gather. An object of class Gather monitors any number of A type threads and any number of B type threads. The purpose of a Gather object is to keep the B threads suspended until all the A threads are finished, then to start all the B threads at precisely the same time. For simplicity, it is OK to assume that no more than 100 A threads will be handled by any Gather object.

In addition, provide simple A and B threads showing how to use your Gather class objects. You may need to provide a main method as well to kick off the threads.

Reasonable Solution:

import java.util.*;

class Gather {
   Hashtable hash = new Hashtable();

   public void waitIt(Process p) {
      if (hash.get(p) != null) return; else hash.put(p,p);
   }
   
   synchronized public void endIt(Process p) {
      if (hash.get(p) != null) hash.remove(p);
      if (hash.isEmpty()) notifyAll();
   }
   
   synchronized void saveIt (Process p) {
      try { System.out.println("\nWait:"+p.id); wait(); } catch (Exception e) { }
      System.out.println("\nRelease:"+p.id);
   }
}

class Process { int id; }

class A extends Process implements Runnable {
   Gather mp;
   Thread runner;
   
   public A (Gather p, int n) {
      runner = new Thread(this);
      mp = p; 
      id = n; 
      p.waitIt(this); 
   }
   
   public void start () { runner.start(); }
   
   public void run () {
      System.out.println("\nStarting "+id);
      for (long i=0 ; i < 10000000 ; i++) if ((i%10000) == 0) System.out.print("\r"+id+":"+i);
      System.out.println("\nTerminating "+id);
      mp.endIt(this);
   }
}

class B extends Process implements Runnable {
   Gather mp;
   Thread runner;
   
   public B (Gather p, int n) {
      runner = new Thread(this);
      mp = p; 
      id = n;
   }
   
   public void start () { runner.start(); }
   
   public void run () {
      System.out.println("\nStarting "+id);
      mp.saveIt(this);
      for (long i=0 ; i < 10000000 ; i++) if ((i%10000) == 0) System.out.print("\r"+id+":"+i);
      System.out.println("\nTerminating "+id);
   }
}

public class T {
   public static void main (String arg[]) {
      Gather g = new Gather();
      A a1 = new A (g,1);
      A a2 = new A (g,2);
      A a3 = new A (g,3);
      A a4 = new A (g,4);
      B b1 = new B (g,5);
      B b2 = new B (g,6);
      B b3 = new B (g,7);

      b1.start();
      a1.start();
      a2.start();
      b2.start();
      a3.start();
      a4.start();
      b3.start();
      
      System.out.println("Go");
   }
}