Java多线程-实现 生产者-消费者 模式

发布时间 2023-08-28 13:57:21作者: YaosGHC

多线程实现生产者消费者,堆积满 100 后停止生产,消费到小于 50 后继续生产

这是一种写法,但是我觉得不太好:

  1. 它通过循环创建了很多的线程,每个线程只消费/生产一次
  2. 它使用notifyAll()通知所有的线程唤醒,包括生产者和消费者,感觉产品数量永远也达不到 50
public class Producer implements Runnable {
    private final Queue<Product> queue;
    private final int maxCapacity;

    public Producer(Queue<Product> queue, int maxCapacity) {
        this.queue = queue;
        this.maxCapacity = maxCapacity;
    }

    @Override
    public void run() {
        synchronized (queue) {
            while (queue.size() == maxCapacity) { //一定要用 while,而不是 if,下文解释
                try {
                    System.out.println("生产者" + Thread.currentThread().getName() + "等待中... Queue 已达到最大容量,无法生产");
                    queue.wait();
                    System.out.println("生产者" + Thread.currentThread().getName() + "退出等待");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            int i = new Random().nextInt();
            queue.offer(new Product("产品" + i));
            System.out.println("生产者" + Thread.currentThread().getName() + "生产了产品:" + i);

            queue.notifyAll();// 通知消费者消费
        }
    }
}

public class Consumer implements Runnable {
    private final Queue<Product> queue;
    private final int minCapacity;

    public Consumer(Queue<Product> queue, int minCapacity) {
        this.queue = queue;
        this.minCapacity = minCapacity;
    }

    @Override
    public void run() {
        synchronized (queue) {
            while (queue.isEmpty()) {
                try {
                    System.out.println("消费者" + Thread.currentThread().getName() + "等待中... Queue 已缺货,无法消费");
                    queue.wait();
                    System.out.println("消费者" + Thread.currentThread().getName() + "退出等待");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            Product product = queue.poll();
            System.out.println("消费者" + Thread.currentThread().getName() + "消费了:" + product.getName());
            if (queue.size() < minCapacity) queue.notifyAll();// 库存小于50,通知生产者生产
        }
    }
}

    public static void main(String[] args) {
        Queue<Product> queue = new ArrayDeque<>();
        for (int i = 0; i < 100; i++) {
            new Thread(new Producer(queue, 100)).start();
            new Thread(new Consumer(queue, 50)).start();
        }
    }