title: Producer Consumer Program using wait() and notify() in Java
body: <p>I am doing classic Producer-Consumer problem in Java using low level synchronization and wait() and notify(). I know there are better implementations using structures from java.util.concurrent package but my problem revolves around low level implementation:</p>
  
  <pre><code>private static ArrayList&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;();
  
      static Object obj = new Object();
  
      public static void producer() throws InterruptedException {
          synchronized (obj) {
              while (true) {
                  if (list.size() == 10) {
                      System.out.println("Queue full.. Waiting to Add");
                      obj.wait();
                  } else {
                      int value = new Random().nextInt(100);
                      if (value &lt;= 10) {
                          Thread.sleep(200);
                          System.out.println("The element added was : " + value);
                          list.add(value);
                          obj.notify();
                      }
                  }
              }
          }
  
      }
  
      public static void consumer() throws InterruptedException {
          synchronized (obj) {
              while (true) {
                  Thread.sleep(500);
                  if (list.size() == 0) {
                      System.out.println("Queue is empty...Waiting to remove");
                      obj.wait();
                  } else {
                      System.out.println("The element removed was : "
                              + list.remove(0));
                      obj.notify();
                  }
              }
          }
  
      }
  </code></pre>
  
  <p>There are 2 threads in the program, 1 each for producer and consumer specifically. The code works just fine. </p>
  
  <p><strong>The only issue</strong> is that producer goes on to produce messages until the maximum at once (until size is 10 for the list), and consumer consumes all 10 at once. </p>
  
  <p>How can I make producer and consumer work at the same time?</p>
  
  <p>This is the sample output:</p>
  
  <pre><code>The element added was : 4
  The element added was : 0
  The element added was : 0
  The element added was : 4
  The element added was : 3
  The element added was : 1
  The element added was : 10
  The element added was : 10
  The element added was : 3
  The element added was : 9
  Queue full.. Waiting to Add
  The element removed was : 4
  The element removed was : 0
  The element removed was : 0
  The element removed was : 4
  The element removed was : 3
  The element removed was : 1
  The element removed was : 10
  The element removed was : 10
  The element removed was : 3
  The element removed was : 9
  Queue is empty...Waiting to remove
  </code></pre>
  
  <p><strong>Edit:</strong> Here is the corrected code:</p>
  
  <pre><code>private static ArrayList&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;();
      private static Object obj = new Object();
  
      public static void producer() throws InterruptedException {
          while (true) {
              Thread.sleep(500);
              if (list.size() == 10) {
                  System.out.println("Waiting to add");
                  synchronized (obj) {
                      obj.wait();
                  }
              }
              synchronized (obj) {
                  int value = new Random().nextInt(10);
                  list.add(value);
                  System.out.println("Added to list: " + value);
                  obj.notify();
              }
          }
      }
  
      public static void consumer() throws InterruptedException {
          while (true) {
              Thread.sleep(500);
              if (list.size() == 0) {
                  System.out.println("Waiting to remove");
                  synchronized (obj) {
                      obj.wait();
                  }
              }
              synchronized (obj) {
                  int removed = list.remove(0);
                  System.out.println("Removed from list: " + removed);
                  obj.notify();
              }
          }
      }
  </code></pre>