用 wait-notify 写一段代码来解决生产者-消费者问题?

使用wait()notify()方法解决生产者-消费者问题是一个经典的多线程同步问题。在这个问题中,我们有一个生产者线程和一个或多个消费者线程共享一个有限容量的缓冲区。生产者生成产品放入缓冲区,消费者从缓冲区中取出产品。

以下是一个简单的Java实现示例,使用了wait()notify()来同步生产者和消费者线程。注意,为了避免虚假唤醒(spurious wakeup),我们通常会在循环中检查条件。

public class ProducerConsumerExample {  
  
    private final int capacity;  
    private int count = 0;  
    private final Object lock = new Object();  
    private int[] buffer;  
  
    public ProducerConsumerExample(int capacity) {  
        this.capacity = capacity;  
        this.buffer = new int[capacity];  
    }  
  
    // 生产者线程  
    public void produce(int item) throws InterruptedException {  
        synchronized (lock) {  
            // 等待缓冲区不满  
            while (count == capacity) {  
                lock.wait();  
            }  
            // 插入元素  
            buffer[count] = item;  
            System.out.println("Produced: " + item);  
            count++;  
            // 通知消费者  
            lock.notify();  
        }  
    }  
  
    // 消费者线程  
    public int consume() throws InterruptedException {  
        synchronized (lock) {  
            // 等待缓冲区不为空  
            while (count == 0) {  
                lock.wait();  
            }  
            // 取出元素  
            int item = buffer[count - 1];  
            count--;  
            System.out.println("Consumed: " + item);  
            // 通知生产者  
            lock.notify();  
            return item;  
        }  
    }  
  
    public static void main(String[] args) {  
        ProducerConsumerExample pc = new ProducerConsumerExample(5);  
  
        // 生产者线程  
        Thread producer = new Thread(() -> {  
            try {  
                for (int i = 0; i < 10; i++) {  
                    pc.produce(i);  
                    Thread.sleep(100); // 模拟耗时操作  
                }  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        });  
  
        // 消费者线程  
        Thread consumer = new Thread(() -> {  
            try {  
                for (int i = 0; i < 10; i++) {  
                    pc.consume();  
                    Thread.sleep(150); // 模拟耗时操作  
                }  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        });  
  
        producer.start();  
        consumer.start();  
    }  
}

注意

  1. lock对象用于同步produce()consume()方法,确保线程安全。
  2. 使用while循环来检查条件(例如缓冲区是否满或空),以防止虚假唤醒导致的问题。
  3. wait()notify()方法必须在同步块中调用,且必须锁定同一个对象。
  4. 在生产者和消费者方法中,调用wait()后线程将被阻塞,直到其他线程调用同一对象的notify()notifyAll()方法。
  5. notifyAll()通常比notify()更安全,因为它可以唤醒所有等待的线程,但在本例中,由于每次只有一个线程能执行(生产者或消费者),使用notify()已足够。然而,在多生产者或多消费者的情况下,建议使用notifyAll()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值