Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 许多生产者和许多消费者。让最后一个生产者活着杀死消费者_Java_Multithreading_Producer Consumer - Fatal编程技术网

Java 许多生产者和许多消费者。让最后一个生产者活着杀死消费者

Java 许多生产者和许多消费者。让最后一个生产者活着杀死消费者,java,multithreading,producer-consumer,Java,Multithreading,Producer Consumer,我有一个标准的生产者消费者问题。生产者将数据放入堆栈(缓冲区),消费者接收数据 我希望有许多生产者和消费者 问题是我只想让最后一个活着的制作人能够调用b.stop() for(int i = 0; i < 10; i++){ try{ // sleep((int)(Math.random() * 1)); }catch(Exception e){e.printStackTrace();} b.

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

我希望有许多生产者和消费者

问题是我只想让最后一个活着的制作人能够调用
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();
他们应该死了,所以我让方法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;
    }

}


stop
方法中,您将
running
设置为
false
,但只要
i==0,while循环就会运行。将
i
设置为与零不同的值,它应该会修复它


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

您必须意识到的是,您的线程可能在两个位置之一等待:

  • wait
    循环中,使用
    i==0
    ——在这种情况下,
    notifyall
    将把它们全部踢出。但是,如果
    i
    仍然是
    0
    ,他们将直接返回等待
  • 等待对对象的独占访问(即等待
    同步
    方法)-在这种情况下(如果您解决了上面的问题1,锁将被释放),它们将直接进入
    而(i==0)
    循环

  • 我建议您将
    while(I==0)
    循环更改为
    while(running&&I==0)
    。这将解决您的问题。由于您的
    正在运行
    标志(正确地)
    易失性
    应整齐退出。

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

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

    您应该向包含生产者数量的
    缓冲区添加一个
    AtomicInteger
    ,并在其构造函数中进行每个生产者调用
    b.start()
    (递增)


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

    我在帖子中忘了更改它。。我有
    while(running&&I==0)
    但问题是我只想让最后一个活着的制作人能够调用
    b.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();
    
        }
    
    }