title: How to make a thread wait until something happens without blocking the others
body: <p>I am making a barbershop simulation using threads in java. A barbershop consists of a waiting room with n chairs and a barber room with several barber chairs. If there are no customers to be served, the barber goes to sleep. If a customer enters the barbershop and all chairs are occupied, then the customer leaves the shop. If the barber is busy but chairs are available, then the customer sits in one of the free chairs. If the barber is asleep, the customer wakes up the barber. </p>
  
  <p>My code so far is working well (I think) but with one mistake. Here the clients go to the barbershop after a random number of milliseconds, and can go there several times. The thing is that if a customer is already at the barbershop, it can't go there again until the service has finished, that means, I need to block the customer thread until the barber finishes cutting his hair, and that's where my code fails. I am pretty sure it must be done with wait() and notify() but when I do that I mess up the rest of threads, probably I am doing something wrong. So how can I sync that? Thanks in advance :)</p>
  
  <p>Here is my code:</p>
  
  <p>Main.java:</p>
  
  <pre><code>public class Main {
  
  public static int tiempoSimulacion;
  
  public static Logger logger = Logger.getLogger("ccia.labarberia");
  static {
      logger.setLevel(Level.OFF)
      //logger.setLevel(Level.WARNING)
      ;}
  
  public static void main(String[] args) throws InterruptedException {
      Scanner sc = new Scanner(System.in);
  
      int nBarberos = sc.nextInt();
      int nClientes = sc.nextInt();
      tiempoSimulacion = sc.nextInt();
  
      Cliente.distribucionNormal = new NormalDistribution(sc.nextInt(),sc.nextInt());
  
      Barbero.distribucionExponencial = new ExponentialDistribution(sc.nextInt());
  
      Barberia b = Barberia.getBarberia(); // La Barberia sigue el patrón Singleton
  
      Cliente.barberia = b;
      Barbero.barberia = b;
      b.setNumeroSillas(sc.nextInt());
      sc.close();
  
      Barbero[] barberos = new Barbero[nBarberos];
      for (int i=1; i&lt;=nBarberos; i++){
          barberos[i-1] = new Barbero(i);
          barberos[i-1].start();
      }
      b.setBarberos(barberos);
  
      Thread[] clientes = new Thread[nClientes];
      for (int j=1; j&lt;=nClientes; j++){
          clientes[j-1] = new Thread(new Cliente(j));
          clientes[j-1].start();
      }
  
      Thread.sleep(tiempoSimulacion*1000);
  
      for (int j=0; j&lt;nClientes; j++){
          clientes[j].interrupt();
      }
  
      for (int i=0; i&lt;nBarberos; i++){
          barberos[i].interrupt();
      }
  
      for (int j=0; j&lt;nClientes; j++){
          clientes[j].join();
      }
  
      for (int i=0; i&lt;nBarberos; i++){
          barberos[i].join();
      }
  
  
  }
  
  }
  </code></pre>
  
  <p>Client.java:</p>
  
  <pre><code>public class Cliente extends Thread{
  
  public static Barberia barberia;
  public static NormalDistribution distribucionNormal;
  
  private int id;
  
  public Cliente (int id) {
      this.id = id;
      System.out.println("El cliente " + id + " se ha creado.");
  }
  
  public int identificador() {
      return this.id;
  }
  
  @Override
  public void run() {
      try{
          while (!Thread.interrupted()) {
              try {
                  Thread.sleep((long)distribucionNormal.sample() );
              } catch (IllegalArgumentException e) {
  
              }
              this.irABarberia();
          }
      }catch (InterruptedException e) {
          System.out.println("El cliente " + this.id + " ha sido destruido.");
      }
  }
  
  public void irABarberia() throws InterruptedException{
      barberia.add(this);
  }
  }
  </code></pre>
  
  <p>Barber.java:</p>
  
  <pre><code>public class Barbero extends Thread{
  
  private static final int OFFSET = 64;
  public static Barberia barberia;
  public static ExponentialDistribution distribucionExponencial;
  private char id;
  
  public Barbero(int i) {
      this.id = (char) (OFFSET + i); 
      System.out.println("El barbero " + this.id + " se ha creado.");
  }
  
  public char identificador() {
      return this.id;
  }
  
  @Override
  public void run() {
      try {
          while(!Thread.interrupted()) {
              barberia.cortarPelo(this);  
          } 
      } catch (InterruptedException ex) {
          System.out.println("El barbero " + this.id + " ha sido destruido.");
      }
  
  }
  }
  </code></pre>
  
  <p>Barbershop.java:</p>
  
  <pre><code>public class Barberia {
  
  private static Barberia mBarberia;
  private static int numSillas;
  private Barbero[] barberos;
  LinkedList&lt;Cliente&gt; listaClientes;
  
  protected Barberia() {
      listaClientes = new LinkedList&lt;Cliente&gt;();
  }
  
  public static Barberia getBarberia() {
      if (mBarberia == null) {
          mBarberia = new Barberia();
      }
      return mBarberia;
  }
  
  public void setNumeroSillas(int sillas) {
      numSillas = sillas;
  }
  
  public void setBarberos(Barbero[] b) {
      this.barberos = new Barbero[b.length];
      for (int i=0; i&lt;this.barberos.length; i++) {
          this.barberos[i] = b[i];
      }
  }
  
  public void cortarPelo(Barbero barbero) throws InterruptedException{
  
      Cliente cliente;
      synchronized (listaClientes) {
          while(listaClientes.size()==0) {
              System.out.println("El barbero " + barbero.identificador() + " se pone a dormir.");
              listaClientes.wait();
          }
          cliente = listaClientes.poll();
  
      }    
      System.out.println("El barbero " + barbero.identificador() + " atiende al cliente " + cliente.identificador() + ".");
      Thread.sleep((long)Barbero.distribucionExponencial.sample() );
      System.out.println("El barbero " + barbero.identificador() + " ha cortado el pelo al cliente " + cliente.identificador() + ".");
  
  }
  
  public void add (Cliente cliente) throws InterruptedException{
       System.out.println("El cliente " + cliente.identificador() + " llega a la barbería.");
       synchronized (listaClientes) {
           if(listaClientes.size() == numSillas) {
               System.out.println("El cliente " + cliente.identificador() + " se marcha sin ser atendido."); 
           } else {
               listaClientes.offer(cliente);
  
               if(listaClientes.size()&gt;0 &amp;&amp; listaClientes.size() &lt;= barberos.length){
                   listaClientes.notify();
               } else {
                   System.out.println("El cliente " + cliente.identificador() + " se sienta en una silla de espera.");
               }  
           }    
       }
  }
  }
  </code></pre>