title: Java thread program not working using wait() and notifyAll()
body: <p>Below is  my program. Always the thread 0 gets the printer, other threads do not get it.
  There is one printer object, and i want multiple job threads to use the printer.  How to make this program work so that all jobs get the printer. For me the code flow seems to be fine. Am synchronizing on a single printer object. Please help.</p>
  
  <pre><code>    package classesTesting;
  
      public class PrinterQueue {
  
          final static Printer printer = new Printer();;
  
          public static void main(String[] args) {
              // TODO Auto-generated method stub
              System.out.println("In Main");
  
              for (int i = 0; i &lt; 5; i++) {
                  new Thread(new Jobs(), "Thread - " + i).start();
                  System.out.println("started " + i + " thread");
              }
  
          }
  
      }
  
      class Printer {
          private boolean isUsed;
  
          Printer() {
              this.isUsed = false;
          }
  
          public void setUsed(boolean used) {
              this.isUsed = used;
          }
  
          public boolean isUsed() {
  
              return this.isUsed;
          }
      }
  
      class Jobs implements Runnable {
  
          String name;
          boolean isDataAvailble;
  
          Jobs() {        
              this.isDataAvailble = true;
          }
  
          public void setNoData(boolean noData) {
              this.isDataAvailble = false;
          }
  
          @Override
          public void run() {
  
              while (isDataAvailble) {
  
                  if (PrinterQueue.printer.isUsed()) {
                      try {
                          System.out.println(Thread.currentThread()
                                  + "WAITING FOR PRINTER");
                          synchronized (PrinterQueue.printer) {
                              PrinterQueue.printer.wait();
                          }
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
  
                  } else {
                      synchronized (PrinterQueue.printer) {
                          System.out.println(Thread.currentThread() + "GOT PRINTER");
                          PrinterQueue.printer.setUsed(true);
                          try {
                              Thread.sleep(3000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          PrinterQueue.printer.setUsed(false);
                          PrinterQueue.printer.notify();
                      }
                  }
              }
  
              try {
                  Thread.sleep(3000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
  
      }
  </code></pre>
  
  <p>Hi, I have revised my program for getting lock first then condition checking. Even then the thread 0 always gets the printer. Other threads starve.</p>
  
  <p>Revised program:</p>
  
  <pre><code>    package classesTesting;
  
      public class PrinterQueue {
  
          static Printer printer;
  
          public static void main(String[] args) {
              // TODO Auto-generated method stub
              System.out.println("In Main");
  
              printer = new Printer();
  
              for (int i = 0; i &lt; 5; i++) {
                  Jobs j1 = new Jobs();
                  j1.setPrinter(printer);
  
                  Thread t1 = new Thread(j1, "Thread - " + i);
                  t1.start();
  
                  System.out.println("started " + i + " thread");
              }
  
          }
  
      }
  
      class Printer {
          private boolean isUsed;
  
          Printer() {
              this.isUsed = false;
          }
  
          public void setUsed(boolean used) {
              this.isUsed = used;
          }
  
          public boolean isUsed() {
  
              return this.isUsed;
          }
      }
  
      class Jobs implements Runnable {
  
          String name;
          Printer printer;
  
          public Printer getPrinter() {
              return printer;
          }
  
          public void setPrinter(Printer printer) {
              this.printer = printer;
          }
  
          boolean isDataAvailble;
  
          Jobs() {
              this.isDataAvailble = true;
          }
  
          public void setNoData(boolean noData) {
              this.isDataAvailble = false;
          }
  
          @Override
          public void run() {
  
              while (isDataAvailble) {
                  synchronized (PrinterQueue.printer) {
                      if (this.printer.isUsed()) {
                          try {
                              System.out.println(Thread.currentThread()
                                      + "WAITING FOR PRINTER");
  
                              PrinterQueue.printer.wait();
  
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
  
                      else {
  
                          System.out.println(Thread.currentThread() + "GOT PRINTER");
  
                          PrinterQueue.printer.setUsed(true);
  
                          try {
                              Thread.sleep(3000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
  
                          PrinterQueue.printer.setUsed(false);
                          PrinterQueue.printer.notify();
                      }
                  }
              }
  
          }
  
      }
  </code></pre>