• Java生产者消费者模式


    生产者消费者模式


    为什么要使用生产者/消费者模式

    在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发
    当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者
    处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费
    者就必须等待生产者。为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消
    费者模式。


    生产者/消费者模型优点

    1、解耦。因为多了一个缓冲区,所以生产者和消费者并不直接相互调用,这一点很容易
    想到,这样生产者和消费者的代码发生变化,都不会对对方产生影响,这样其实就把生产
    者和消费者之间的强耦合解开,变为了生产者和缓冲区/消费者和缓冲区之间的弱耦合
    2、通过平衡生产者和消费者的处理能力来提高整体处理数据的速度,这是生产者/消费者
    模型最重要的一个优点。如果消费者直接从生产者这里拿数据,如果生产者生产的速度很
    慢,但消费者消费的速度很快,那消费者就得占用CPU的时间片白白等在那边。有了生产
    者/消费者模型,生产者和消费者就是两个独立的并发体,生产者把生产出来的数据往缓
    冲区一丢就好了,不必管消费者;消费者也是,从缓冲区去拿数据就好了,也不必管生产
    者,缓冲区满了就不生产,缓冲区空了就不消费,使生产者/消费者的处理能力达到一个
    动态的平衡

    生产者/消费者模式的作用

    • - 支持并发
    • - 解耦
    • - 支持忙闲不均

    编码体现 

    1. public class Basket {
    2. private volatile Object obj = null; // 利用volatile保证可见性
    3. public synchronized void produce(Object obj) {
    4. while (this.obj != null) {
    5. try {
    6. // this.wait();// 当前线程进入minitor的waitSet中
    7. Thread.sleep(100);
    8. } catch (InterruptedException e) {
    9. e.printStackTrace();
    10. }
    11. }
    12. this.obj = obj;
    13. this.notifyAll(); // 唤醒处于waitSet中的所有线程
    14. System.out.println("生产了一个对象:" + obj);
    15. }
    16. public synchronized void consume() {
    17. while (obj == null)
    18. try {
    19. // this.wait();
    20. Thread.sleep(100);
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. }
    24. System.out.println("消费了一个对象:" + obj);
    25. this.obj = null;
    26. this.notifyAll();
    27. }
    28. }
    1. public class Consumer implements Runnable {
    2. private Basket resource = null;
    3. public Consumer(Basket resource) {
    4. this.resource = resource;
    5. }
    6. public void run() {
    7. for (int i = 0; i < 20; i++) {
    8. resource.consume();
    9. }
    10. }
    11. }
    1. public class Producer implements Runnable {
    2. private Basket resource = null;
    3. public Producer(Basket resource) {
    4. this.resource = resource;
    5. }
    6. public void run() {
    7. for (int i = 0; i < 20; i++) {
    8. Object obj = new Date();
    9. resource.produce(obj);
    10. }
    11. }
    12. }
    1. public class Test {
    2. public static void main(String[] args) {
    3. Basket resource = new Basket();
    4. new Thread(new Producer(resource)).start();
    5. new Thread(new Consumer(resource)).start();
    6. }
    7. }

    wait和notify/notifyAll的用法

    调用wait/notify之类的方法要求必须在当前线程对象内部,例如synchronized方法中 

    - 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。不能更改为sleep,因为sleep不会释放锁
    - 当执行notify/notifyAll方法时,会唤醒一个处于等待该对象锁的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。 

  • 相关阅读:
    2020秋招Java面试题
    轻松连接:简化编程中的连接操作
    RHCSA2
    王道操作系统___第四章01
    12【事务的隔离级别】
    【电源专题】电源芯片散热垫(PowerPAD)布局指南
    SSM
    安装Docker
    opencv之cv2.findContours和drawContours(python)
    【推送服务】【FAQ】Push Ki常见咨询合集6--消息报表类问题
  • 原文地址:https://blog.csdn.net/weixin_50518344/article/details/126453980