【问题标题】:Many ProducerS and many ConsumerS. Making the last producer alive killing the consumers许多生产者和许多消费者。让最后一个生产者活着杀死消费者
【发布时间】:2013-04-20 22:34:22
【问题描述】:

我有一个标准的生产者消费者问题。生产者将数据放入堆栈(缓冲区),消费者获取。

我希望有很多生产者和消费者。

问题是我只想让最后一个活着的制作人能够打电话给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()Buffer 中的running 字段更改为false 和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();

    }

}

【问题讨论】:

    标签: java multithreading producer-consumer


    【解决方案1】:

    您必须意识到,您的线程可能在两个位置中的任何一个处等待:

    1. 在带有i == 0wait 循环中 - 在这种情况下,notifyall 会将它们全部踢出。但是,如果 i 仍然是 0,他们将直接返回等待。
    2. 等待对对象的独占访问(即等待synchronized 方法) - 在这种情况下(如果您修复了上面的问题 1 并且锁将被释放),它们将直接进入while (i == 0) 循环。

    我建议您将while ( i == 0 ) 循环更改为while ( running &amp;&amp; i == 0 )。这应该解决您的问题。因为你的running 标志是(正确的)volatile,所以所有的人都应该整齐地退出。

    【讨论】:

    • 我忘了在帖子中更改它。我有while ( running &amp;&amp; i == 0 ),但问题是我只想让最后一个活着的制作人能够打电话给b.stop()
    【解决方案2】:

    在您的stop 方法中,您将running 设置为false,但您的while 循环运行时间与i == 0 一样长。将i 设置为不同于零的值,它应该可以修复它。

    顺便说一句,我不明白你为什么有一个 running 变量和一个单独的 i 变量,这实际上是保持线程运行的变量。

    【讨论】:

      【解决方案3】:

      我会重新考虑您的设计。类应该有一套连贯的职责;让一个类负责消费队列中的对象,同时负责关闭其他消费者,这似乎是您想要分开的事情。

      【讨论】:

        【解决方案4】:

        为了回答只让最后一个活着的生产者能够调用 b.stop()

        您应该在Buffer 中添加一个AtomicInteger,其中包含生产者的数量,并让每个生产者在其构造函数中调用b.start()(递增它)。

        这样您可以在b.stop() 中减少它,并且只有当它变为零时,才应将running 设置为false

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-08
          • 2013-03-06
          • 2012-01-10
          相关资源
          最近更新 更多