title: Produce Consumer
body: <p>I tried to implement <strong>Producer Consumer</strong> pattern with <code>wait()</code> and <code>notifyAll()</code> methods, but have some issues. So my code is next.</p>
  
  <p><strong>Main class</strong>:</p>
  
  <pre><code>import java.util.LinkedList;
  import java.util.List;
  
  public class TestThread {
  
      public static void main(String[] args) {
          final List testQueue = new LinkedList();
  
          final Producer producer = new Producer(testQueue);
          final Consumer consumer = new Consumer(testQueue);
  
          Runnable prodThread = new Runnable() {
              @Override
              public void run() {
                  producer.putMessages();
              }
          };
          Runnable consThread = new Runnable() {
              @Override
              public void run() {
                  consumer.readMessages();
              }
          };
  
          (new Thread(prodThread)).start();
          (new Thread(consThread)).start();
      }
  }
  </code></pre>
  
  <p><strong>Produce class</strong>:</p>
  
  <pre><code>class Producer {
      private final List queue;
  
      public Producer(List queue) {
          this.queue = queue;
      }
  
      public void putMessages() {
          // Add batch of messages to queue
          for (int t = 1; t &lt;= 2; t++) {
              synchronized (queue) {
                  try {
                      // if size of queue is more then 2, then wait
                      while (queue.size() &gt; 1) {
                          System.out.println("Producer: Queue is full! Size of queue is " + queue.size() +", so Producer is waiting...");
                          queue.wait();
                          // Consumer could start own work here
                      }
                      for (int i = 0; i &lt; 2; i ++) {
                          queue.add("String" + (i+1)*t);
                          System.out.println("Producer: Message -" + queue.get(i) + "- was added to queue...");
                      }
                      System.out.println("Producer added batch of messages, let's notify our Consumer...");
                      queue.notifyAll(); // consumer thread should be in wait set
                  }
                  catch(Exception ex) {
                      ex.printStackTrace();
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>Consumer class</strong>:</p>
  
  <pre><code>class Consumer {
      private final List queue;
  
      public Consumer(List queue) {
          this.queue = queue;
      }
  
      public void readMessages() {
          synchronized (queue) {
              try {
                  //while queue is empty let's wait - producer will get processor time in this case
                  while (queue.isEmpty()) {
                      System.out.println("Consumer: Queue is empty! Nothing to read, so Consumer is waiting...");
                      queue.wait();
                  }
                  for (int k = 0; k &lt; queue.size(); k++) {
                      System.out.println("Consumer: Read messages from queue -" + queue.get(k) + " -");
                  }
                  //clean our queue
                  queue.removeAll(queue);
                  if (queue.isEmpty()) {
                      System.out.println("Consumer finished reading, notify Producer that queue is empty, please start adding new messages for me!");
                      queue.notifyAll();
                  }
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
          }
      }
  }
  </code></pre>
  
  <p>The result of program execution:</p>
  
  <pre><code>Consumer: Queue is empty! Nothing to read, so Consumer is waiting...
  Producer: Message -String1- was added to queue...
  Producer: Message -String2- was added to queue...
  Producer added batch of messages, let's notify our Consumer...
  Consumer: Read messages from queue -String1 -
  Consumer: Read messages from queue -String2 -
  Consumer finished reading, notify Producer that queue is empty, please start adding new messages for me!
  Producer: Message -String2- was added to queue...
  Producer: Message -String4- was added to queue...
  Producer added batch of messages, let's notify our Consumer...
  </code></pre>
  
  <p>Based on my code I'm expecting that <strong>Consumer</strong> read last messages from <strong>Producer</strong> (<code>String2</code>, <code>String4</code>) and print the result. But it is not happen, what is wrong with my code?</p>