title: Consumers producer multithreading consumers are not dying
body: <p>I have a standard producer consumer problem. Producer puts data into the stack(buffer) consumers take it.
  The problem is that consumers are not dying(not always) when the producer ends producing the data. </p>
  
  <p>I would like to make consumer die after producer ends his <code>for</code> loop </p>
  
  <pre><code>for(int i = 0; i &lt; 10; i++){
          try{
      //      sleep((int)(Math.random() * 1));                
          }catch(Exception e){e.printStackTrace();}
          b.put((int) (Math.random()* 10));
          System.out.println("i = " + i);
      }
      b.stop();
  </code></pre>
  
  <p>so then I call <code>b.stop()</code> which changes <code>running</code> field in <code>Buffer</code> to false and <code>notifiesAll()</code></p>
  
  <p>End then I get:</p>
  
  <pre><code>i = 9 // number of iteration this is 10th iteration
  Consumer 2.: no data to take. I wait.  Memory: 0
  Consumer 1.: no data to take. I wait.  Memory: 0
  Consumer 3.: no data to take. I wait.  Memory: 0
  </code></pre>
  
  <p>they should die then, so I made method stop() but it did not work.</p>
  
  <p>Code is running please check it</p>
  
  <pre><code>import java.util.Stack;
  
  
  public class Buffer {
  private static int SIZE = 4;
  private int i;//number of elements in buffer
  public Stack&lt;Integer&gt; stack;
  private volatile boolean running;
      public Buffer() {
          stack = new Stack&lt;&gt;();
          running = true;
          i = 0;
      }
      synchronized public void put(int val){
          while (i &gt;= SIZE) {
              try {
                  System.out.println("Buffer full, producer waits");
                  wait();
              } catch (InterruptedException exc) {
                  exc.printStackTrace();
              }
          }   
          stack.push(val);//txt = s;
          i++;
          System.out.println("Producer inserted " + val + " memory: " + i);
          if(i - 1 == 0)
              notifyAll();
          System.out.println(stack);
      }
  
      public synchronized Integer get(Consumer c) {
          while (i == 0) {
              try {
                  System.out.println(c + ": no data to take. I wait.  Memory: " + i);
                  wait();
              } catch (InterruptedException exc) {
                  exc.printStackTrace();
              }
          }   
          if(running){
              int data = stack.pop();
              i--;    
              System.out.println(c+  ": I took: " + data +" memory: " +  i);
              System.out.println(stack);
              if(i + 1 == SIZE){//if the buffer was full so the producer is waiting
                  notifyAll();
                  System.out.println(c +  "I notified producer about it");
          }
          return data;}
          else 
              return null;
      }
  
      public boolean isEmpty(){
          return i == 0;
      }
      public synchronized void stop(){//I THOUGH THIS WOULD FIX IT~!!!!!!!!!!!!!!
          running = false;
          notifyAll();
      }
      public boolean isRunning(){
          return running;
      }
  
  }
  </code></pre>
  
  <hr>
  
  <pre><code>public class Producer extends Thread {
  private Buffer b;
      public Producer(Buffer b) {
          this.b = b;
      }
  
      public void run(){
          for(int i = 0; i &lt; 10; i++){
              try{
          //      sleep((int)(Math.random() * 1));                
              }catch(Exception e){e.printStackTrace();}
              b.put((int) (Math.random()* 10));
              System.out.println("i = " + i);
          }
          b.stop();
      }
  
  }
  </code></pre>
  
  <hr>
  
  <pre><code>public class Consumer extends Thread {
      Buffer b;
      int nr;
      static int NR = 0;
  
      public Consumer(Buffer b) {
          this.b = b;
          nr = ++NR;
      }
  
      public void run() {
          Integer i = b.get(this);
          while (i != null) {
              System.out.println(nr + " I received : " + i);
              i = b.get(this);
          }
          System.out.println("Consumer " + nr + " is dead");
      }
  
      public String toString() {
          return "Consumer " + nr + ".";
  }
  
  }
  </code></pre>
  
  <hr>
  
  <pre><code>public class Main {
  
      public static void main(String[] args) {
  
          Buffer b = new Buffer();
          Producer p = new Producer(b);
          Consumer c1 = new Consumer(b);
          Consumer c2 = new Consumer(b);
          Consumer c3 = new Consumer(b);  
          p.start();
          c1.start();c2.start();c3.start();
  
      }
  
  }
  </code></pre>