public void adjustTellerNumber() {
   // This is actually a control system. By adjusting
   // the numbers, you can reveal stability issues in
   // the control mechanism.
   // If line is too long, add another teller:
   if (customers.size() / workingTellers.size() > 2) {
     // If tellers are on break or doing
     // another job, bring one back:
     if (tellersDoingOtherThings.size() > 0) {
       Teller teller = tellersDoingOtherThings.remove();
       teller.serveCustomerLine();
       workingTellers.offer(teller);
       return;
     }
     // Else create (hire) a new teller
     Teller teller = new Teller(customers);
     exec.execute(teller);
     workingTellers.add(teller);
     return;
   }
   // If line is short enough, remove a teller:
   if (workingTellers.size() > 1 && customers.size() / workingTellers.size() < 2)
     reassignOneTeller();
   // If there is no line, we only need one teller:
   if (customers.size() == 0) while (workingTellers.size() > 1) reassignOneTeller();
 }
 public void run() {
   try {
     while (!Thread.interrupted()) {
       TimeUnit.MILLISECONDS.sleep(rand.nextInt(300));
       customers.put(new Customer(rand.nextInt(1000)));
     }
   } catch (InterruptedException e) {
     System.out.println("CustomerGenerator interrupted");
   }
   System.out.println("CustomerGenerator terminating");
 }
 public void run() {
   try {
     while (!Thread.interrupted()) {
       Customer customer = customers.take();
       TimeUnit.MILLISECONDS.sleep(customer.getServiceTime());
       synchronized (this) {
         customersServed++;
         while (!servingCustomerLine) wait();
       }
     }
   } catch (InterruptedException e) {
     System.out.println(this + "interrupted");
   }
   System.out.println(this + "terminating");
 }