我正在尝试使用Java中的监视器解决单个消费者/生产者问题,代码如下。当我运行此代码时,它最终会卡住。最典型的情况是,消费者调用wait(),然后生产者继续生产,但无法通知消费者(尽管它将调用notify())。我不知道为什么会这样。 Java代码:

import java.util.*;
class Monitor {
    int length;
    int size;
    int begin, end;
    int queue[];
    private static Random randGenerator;
    public Monitor() {}
    public Monitor(int length) {
        this.length = length;
        this.size = 0;
        begin = end = 0;
        queue = new int[length];
        randGenerator = new Random(10);
    }
    public synchronized void produce() throws InterruptedException {
        while(size == length) {
            System.out.println("Producer waiting");
            wait();
        }
        int produced = randGenerator.nextInt();
        size++;
        queue[end] = produced;
        end = (end + 1) % length;
        System.out.println("Produce element " + produced + " size "+size);
        // When size is not 1, no thread is blocked and therefore don't need to notify
        if(size == 1) {
            System.out.println("Notify consumer");
            notify();
        }
    }
    public synchronized void consume() throws InterruptedException {
        while(size == 0) {
            System.out.println("Consumer waiting, size " + size);
            wait();
        }
        size--;
        System.out.println("Consume element " + queue[begin] + " size " + size);
        begin = (begin + 1) % length;
        if(size == length - 1) {
            System.out.println("Notify producer");
            notify();
        }
    }
}

class Producer implements Runnable {
    Monitor producer;
    public Producer(Monitor m) {
        producer = m;
    }
    @Override
    public void run() {
        producer = new Monitor();
        System.out.println("Producer created");
        try {
            while(true) {
                producer.produce();
            }
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class Consumer implements Runnable {
    Monitor consumer;
    public Consumer(Monitor m) {
        consumer = m;
    }
    @Override
    public void run() {
        System.out.println("Consumer created");
        consumer = new Monitor();
        try {
            while(true) {
                consumer.consume();
            }
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class monitorTest {
    public static void main(String args[]) {
        Monitor monitor = new Monitor(10);
        Thread t1 = new Thread(new Producer(monitor));
        Thread t2 = new Thread(new Consumer(monitor));
        t1.start();
        t2.start();
    }
}

最佳答案

当每个线程的控件进入produce()consume()方法时,大小和长度均为零,因此两个线程都在等待另一个线程通知。打破这一点,您的代码将摆脱僵局。

public synchronized void produce() throws InterruptedException {
    while(size == length) { // size is 0 and length is 0; so wait
        System.out.println("Producer waiting");
        wait();
    }




public synchronized void consume() throws InterruptedException {
    while(size == 0) { // size is 0 so wait
        System.out.println("Consumer waiting, size " + size);
        wait();
    }




发生这种情况是因为您有一个默认的构造函数,您正在Producer和Consumer对象的run()方法内调用它。

class Producer implements Runnable {
    Monitor producer;
    public Producer(Monitor m) {
        producer = m;
    }
    @Override
    public void run() {
        producer = new Monitor(); // REMOVE THIS

class Consumer implements Runnable {
    Monitor consumer;
    public Consumer(Monitor m) {
        consumer = m;
    }
    @Override
    public void run() {
        System.out.println("Consumer created");
        consumer = new Monitor(); // AND REMOVE THIS




希望这可以帮助!

10-08 18:32