当前位置: 首页 > news >正文

学习笔记07——生产者-消费者模型4种实现方式

在Java中,生产者-消费者模型可以通过多种方式实现。以下是常见的几种实现方法及其代码示例:


 1. 使用 `wait()` 和 `notify()`(基础同步机制)
通过 `synchronized` 块和 `Object` 的等待/唤醒机制实现。
 

public class WaitNotifyExample {
    private final Queue<Integer> queue = new LinkedList<>();
    private final int MAX_SIZE = 10;

    public void produce() throws InterruptedException {
        while (true) {
            synchronized (queue) {
                while (queue.size() == MAX_SIZE) {
                    queue.wait(); // 队列满时等待
                }
                int value = new Random().nextInt(100);
                queue.add(value);
                System.out.println("生产: " + value);
                queue.notifyAll(); // 唤醒消费者
            }
            Thread.sleep(500);
        }
    }

    public void consume() throws InterruptedException {
        while (true) {
            synchronized (queue) {
                while (queue.isEmpty()) {
                    queue.wait(); // 队列空时等待
                }
                int value = queue.poll();
                System.out.println("消费: " + value);
                queue.notifyAll(); // 唤醒生产者
            }
            Thread.sleep(1000);
        }
    }
}

 2. 使用 `BlockingQueue`(线程安全队列)
直接利用 `BlockingQueue` 的阻塞特性简化代码。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class BlockingQueueExample {
    private final BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);

    public void produce() throws InterruptedException {
        while (true) {
            int value = new Random().nextInt(100);
            queue.put(value); // 队列满时自动阻塞
            System.out.println("生产: " + value);
            Thread.sleep(500);
        }
    }

    public void consume() throws InterruptedException {
        while (true) {
            int value = queue.take(); // 队列空时自动阻塞
            System.out.println("消费: " + value);
            Thread.sleep(1000);
        }
    }
}

 3. 使用 `Lock` 和 `Condition`(更灵活的锁)
通过显式锁和条件变量实现细粒度控制。

import java.util.concurrent.locks.*;
import java.util.Queue;
import java.util.LinkedList;

public class LockConditionExample {
    private final Queue<Integer> queue = new LinkedList<>();
    private final int MAX_SIZE = 10;
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public void produce() throws InterruptedException {
        while (true) {
            lock.lock();
            try {
                while (queue.size() == MAX_SIZE) {
                    notFull.await(); // 等待队列不满
                }
                int value = new Random().nextInt(100);
                queue.add(value);
                System.out.println("生产: " + value);
                notEmpty.signal(); // 唤醒消费者
            } finally {
                lock.unlock();
            }
            Thread.sleep(500);
        }
    }

    public void consume() throws InterruptedException {
        while (true) {
            lock.lock();
            try {
                while (queue.isEmpty()) {
                    notEmpty.await(); // 等待队列不空
                }
                int value = queue.poll();
                System.out.println("消费: " + value);
                notFull.signal(); // 唤醒生产者
            } finally {
                lock.unlock();
            }
            Thread.sleep(1000);
        }
    }
}

 4. 使用 `Semaphore`(信号量控制资源)
通过信号量管理可用资源数量。

import java.util.concurrent.Semaphore;
import java.util.Queue;
import java.util.LinkedList;

public class SemaphoreExample {
    private final Queue<Integer> queue = new LinkedList<>();
    private final int MAX_SIZE = 10;
    private final Semaphore semProducer = new Semaphore(MAX_SIZE);
    private final Semaphore semConsumer = new Semaphore(0);
    private final Object lock = new Object();

    public void produce() throws InterruptedException {
        while (true) {
            semProducer.acquire(); // 获取生产许可
            synchronized (lock) {
                int value = new Random().nextInt(100);
                queue.add(value);
                System.out.println("生产: " + value);
            }
            semConsumer.release(); // 释放消费许可
            Thread.sleep(500);
        }
    }

    public void consume() throws InterruptedException {
        while (true) {
            semConsumer.acquire(); // 获取消费许可
            synchronized (lock) {
                int value = queue.poll();
                System.out.println("消费: " + value);
            }
            semProducer.release(); // 释放生产许可
            Thread.sleep(1000);
        }
    }
}

总结
以上四种是Java中实现生产者-消费者的主流方式:
1. `wait()/notify()`:适合基础场景,需手动处理同步。
2. `BlockingQueue`:代码最简洁,推荐优先使用。
3. `Lock` + `Condition`:提供更灵活的锁控制。
4. `Semaphore`:通过资源计数管理同步,需注意线程安全。

根据具体需求(如性能、复杂度、可扩展性)选择合适的方式。


文章转载自:

http://icF2pVZZ.mftdq.cn
http://yj6l30l3.mftdq.cn
http://98pmzZyt.mftdq.cn
http://7hsP4h8s.mftdq.cn
http://2rLWqd6Y.mftdq.cn
http://PZrjdz1b.mftdq.cn
http://z8u8Qcwe.mftdq.cn
http://8hVDDsDD.mftdq.cn
http://687WMOKw.mftdq.cn
http://k1p31NYH.mftdq.cn
http://V7vKOAqt.mftdq.cn
http://aiH0nEpt.mftdq.cn
http://apxYYIjk.mftdq.cn
http://9cHh55pR.mftdq.cn
http://30ZFGUSR.mftdq.cn
http://dbfngIne.mftdq.cn
http://RyY6IR4p.mftdq.cn
http://Gj4GqAMv.mftdq.cn
http://eqZs992L.mftdq.cn
http://vNP9Q6SR.mftdq.cn
http://Gt4jiB3H.mftdq.cn
http://pEy9qthh.mftdq.cn
http://YPk0Uoct.mftdq.cn
http://bwiHfcgW.mftdq.cn
http://uVcQ4UnA.mftdq.cn
http://X85cF1s5.mftdq.cn
http://QQxBAeMH.mftdq.cn
http://MRC6kZ62.mftdq.cn
http://RzSLNI32.mftdq.cn
http://SdvK91O0.mftdq.cn
http://www.dtcms.com/a/45593.html

相关文章:

  • LLM 大语言模型定义以及关键技术术语认知
  • MySQL表字段数量上限解析
  • 平衡二叉树
  • web前端基础修炼手册
  • Android Logcat 高效调试指南
  • 【算法题解答·一】二分法
  • JavaScript知识点5
  • 新生校园报道小程序毕业系统设计
  • 内容中台与企业内容管理架构解析
  • 变电站蓄电池在线监测系统(论文+源码)
  • NIO是什么?它与传统的IO有什么区别?
  • 网络运维学习笔记(DeepSeek优化版)009网工初级(HCIA-Datacom与CCNA-EI)路由理论基础与静态路由
  • 计算机毕设-基于springboot的社团管理系统的设计与实现(附源码+lw+ppt+开题报告)
  • 无人机自主导航与避障技术!
  • python脚本将mysql数据写入doris
  • Ubuntu 下查看进程 PID 和终止进程方法
  • 【初阶数据结构和算法】初识树与二叉树的概念以及堆和完全二叉树之间的关系
  • JPA属性转换器的使用与实例解析
  • python中单例模式介绍(含线程安全的单例模式)
  • 第一个Vue项目笔记(待更新)
  • 从零基础到通过考试
  • WebRTC与PJSIP:呼叫中心系统技术选型指南
  • 5分钟看懂Deepseek开源周之六:Deepseek-V3/R1推理系统设计----揭开深度求索模型系统设计和运营成本之谜
  • 《HelloGitHub》第 107 期
  • 红黑树和 STL —— set和map 【复习笔记】
  • 【SpringBoot】脚手架搭建(IDEA)流程
  • 【GenBI优化】提升text2sql准确率:建议使用推理大模型,增加重试
  • mysql.gtid_executed表、gtid_executed变量、gtid_purged变量的修改时机
  • 算法-二叉树篇22-二叉搜索树的最近公共祖先
  • mysql系列10—mysql锁