基于wait/notify方法 实现生产/消费者模型

java 复制代码
public class RunBlockQueue<T> {

    private Integer maxSize;

    private Queue<T> queue;

    public RunBlockQueue(Integer maxSize) {
        this.maxSize = maxSize;
        this.queue = new ArrayDeque<>();
    }

    //生产者添加消息
    public synchronized void add(T t)  throws Exception{
        //这里是while循环,防止线程被唤醒后继续添加
        while (queue.size() >= maxSize) {
            System.out.println(Thread.currentThread().getName() + "队列已满,进入休眠,释放锁");
            wait();
        }
        //生产者生产消息
        queue.add(t);
        //通知消费者进行消费
        this.notifyAll();
    }

    //消费者消费消息
    public synchronized T get() throws Exception{
        while (queue.size() == 0){
            //当前线程休眠 并释放锁
            this.wait();
        }
        //消费
        T poll = queue.poll();
        //消费了消息,通知生产者去生产
        this.notifyAll();
        return poll;
    }

    public static void main(String[] args) throws Exception {

        RunBlockQueue<String> queue = new RunBlockQueue<>(10);

        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                while (true){
                    try {
                        String data = UUID.randomUUID().toString();
                        queue.add(data);
                        System.out.println(Thread.currentThread().getName() + " 生产了数据 ===> " + data);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        new Thread(() -> {
            while (true){
                String data = null;
                try {
                    data = queue.get();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " 消费了数据 ===> " + data);
            }
        }).start();

    }

}
复制代码
消费/生产者模型
    1. 当所有生产者达到生产阈值时,必须保证所有生产者都休眠,不会再去竞争锁,
    2. 当所有消费者达到消费阈值时,必须保证所有消费者都休眠,不会再去竞争锁,让生产者去获取到锁去生产消息。
    3. 当生产者没有达到生产阈值时,不需要休眠,依然可以继续竞争锁。
    4. 当消费者没有达到消费阈值时,不需要休眠,依然可以继续竞争锁。

    5. 生产/消费者 的方法同时只能执行一个方法
        生产者每生产完消息后,会notifyAll唤醒或有线程(包括消费者,如果消费者能竞争得到锁)
        消费者每消费完消息后,会notifyAll唤醒或有线程(包括生产者,如果生产者能竞争得到锁)

当消费者每消费完一个消息,都会执行notify方法,这样可以保证唤醒所有生产/消费线程

不管是生产/消费谁拿到锁,都会判断是否达到阈值,如果达到。

确保生产/消费不会同时休眠就是要保证判断条件不会同时满足休眠,例如生产者是队列满时才休眠,消费者是队列空时才休眠,这两个条件显示不会同时满足,所以不会造成 生产/消费 同时休眠。

相关推荐
ejinxian1 小时前
PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等数据库
数据库·mysql·mongodb
折哥的程序人生 · 物流技术专研7 小时前
Java面试85题图解版 · 特别篇:2026后端高频面试题复盘(算法底层逻辑+高并发架构设计全解析,附Java实战代码)
java·网络·数据库·算法·面试
AOwhisky7 小时前
Redis 学习笔记(第三期):持久化与主从复制
运维·数据库·redis·笔记·学习·云计算
李白的天不白7 小时前
数据库连接报错问题
数据库
一条泥憨鱼7 小时前
【Redis】数据类型和常用命令
java·数据库·redis·后端·缓存
云烟成雨TD8 小时前
Spring AI Alibaba 1.x 系列【78】沙箱(Sandbox)
java·人工智能·spring
程序员二叉8 小时前
【Java】 异常高频面试题精讲 | 易错点+对比总结
java·开发语言·面试
爱喝水的鱼丶8 小时前
SAP-ABAP:SAP视图开发入门:四类标准视图的适用场景与创建步骤详解
服务器·数据库·性能优化·sap·abap
周航宇JoeZhou8 小时前
JB3-9-SpringAI(二)
java·ai·agent·多智能体·调度·智能体·观察
好家伙VCC8 小时前
Web Components主题热切换方案揭秘
java·前端