2013-04-20 4 views
2

У меня есть стандартная проблема потребителей-производителей. Производитель помещает данные в стек (буфер) потребители берут его.Многие производители и многие потребители. Превращение последнего продюсера в убийство потребителей

Я хотел бы иметь много производителей и потребителей.

проблема, я хотел бы сделать только последний производитель гостиной, чтобы быть в состоянии назвать b.stop()

for(int i = 0; i < 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(); 

так, то я называю b.stop(), который изменяет running поле в Buffer ложь и notifiesAll()

Конец, то я получаю:

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 

они должны умереть, поэтому я сделал метод stop(), но это не сработало.

код работает, пожалуйста, проверьте его

import java.util.Stack; 


public class Buffer { 
private static int SIZE = 4; 
private int i;//number of elements in buffer 
public Stack<Integer> stack; 
private volatile boolean running; 
    public Buffer() { 
     stack = new Stack<>(); 
     running = true; 
     i = 0; 
    } 
    synchronized public void put(int val){ 
     while (i >= 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; 
    } 

} 

public class Producer extends Thread { 
private Buffer b; 
    public Producer(Buffer b) { 
     this.b = b; 
    } 

    public void run(){ 
     for(int i = 0; i < 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(); 
    } 

} 

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 + "."; 
} 

} 

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(); 

    } 

} 

ответ

0

В вашем методе stop вы устанавливаете running до false, но ваш цикл while работает до i == 0. Установите i на что-то отличное от нуля, и оно должно исправить его.

BTW, я не понимаю, почему у вас есть переменная running и отдельная переменная i, которая на самом деле является переменной, поддерживающей поток.

1

То, что вы должны понимать, что ваши потоки могли ждать ни в одном из двух мест:

  1. В цикле wait с i == 0 - в этом случае notifyall будет удар все из них. Однако, если i все еще 0, они вернутся обратно к ожиданию снова.
  2. Ожидание эксклюзивного доступа к объекту (т. Е. Ожидание по методу synchronized) - в этом случае (если вы исправите проблему 1 выше и блокировка будет выпущена), они перейдут прямо в цикл while (i == 0).

Я предлагаю вам сменить вашу while (i == 0) петлю на while (running && i == 0). Это должно исправить вашу проблему. Так как ваш running флаг (правильно) volatile все должны аккуратно выйти.

+0

Я забыл изменить его в сообщении .. У меня есть 'while (running && i == 0)', но проблема в том, что я хочу сделать только последнего живого продюсера, чтобы иметь возможность называть 'b.stop () ' – 2013-04-21 11:41:03

+0

Я отредактировал мой вопрос, этот был старый, извините. – 2013-04-21 11:43:30

0

Я бы передумал ваш дизайн. Классы должны иметь согласованный набор обязанностей; создание класса, ответственного за уничтожение объектов, находящихся в очереди, а также ответственность за закрытие других пользователей, похоже, является чем-то, что вы хотели бы разделить.

0

В ответ на , чтобы сделать только последнего живого продюсера, чтобы иметь возможность позвонить b.stop().

Вы должны добавить AtomicInteger к вашему Buffer, содержащему количество производителей, и сделать звонок каждого производителя b.start() (что увеличивает его) в его конструкторе.

Таким образом, вы можете уменьшить его в b.stop(), и только тогда, когда он достиг нулевого уровня, необходимо установить running на false.

Смежные вопросы