首页 > 其他分享 >生产者消费者设计模式

生产者消费者设计模式

时间:2024-07-22 21:10:41浏览次数:10  
标签:消费者 生产者 buffer 线程 缓冲区 设计模式 数据

生产者消费者设计模式学习

一、什么是生产者消费者设计模式

Java中的生产者-消费者设计模式是一种用于多线程编程的经典设计模式,它用于解决多个线程之间共享资源时的同步和通信问题。这个模式主要用在有数据生产者(Producer)和数据消费者(Consumer)的场景中,生产者负责产生数据,而消费者负责消费数据。

二、为什么会有这种模式

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

三、是用来解决什么问题的

  • 资源共享:在多线程环境中安全地共享资源。
  • 数据同步:确保生产者不会在没有消费者的情况下过度填充缓冲区,反之亦然。
  • 异步通信:允许生产者和消费者独立工作,但又能在适当的时候交互。

四、如何解决的

上个小demo

package com.ljh.producerconsumer;

import java.util.LinkedList;
import java.util.Queue;

public class producerConsumerDemo {
    public static void main(String[] args) {
        Buffer buffer=new Buffer();
        Consumer consumer=new Consumer(buffer);
        Producer producer=new Producer(buffer);
        
        producer.start();
        consumer.start();


    }
}

/**
 * 生产者类,继承自Thread,负责向缓冲区添加数据。
 * 该类的实例将作为一个线程运行,不断地向缓冲区添加数据。
 */
class Producer extends Thread {
    /**
     * 缓冲区对象,用于存储生产者产生的数据。
     */
    private Buffer buffer;

    /**
     * 构造函数,初始化生产者的缓冲区。
     * 
     * @param buffer 缓冲区实例,生产者将向这个缓冲区添加数据。
     */
    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }

    /**
     * 重写run方法,定义生产者的线程执行逻辑。
     * 生产者会循环10次,每次向缓冲区添加一个数字,并休眠1秒。
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                // 向缓冲区添加数据。
                buffer.add(i);
                // 休眠1秒,模拟生产数据的过程。
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 如果线程被中断,抛出运行时异常。
                throw new RuntimeException(e);
            }
        }
    }
}

/**
 * 消费者类,继承自Thread,负责从缓冲区获取数据并消费。
 */
class Consumer extends Thread {
    /**
     * 缓冲区对象,用于存储和提取数据。
     */
    private Buffer buffer;

    /**
     * 构造函数,初始化消费者类的缓冲区对象。
     * 
     * @param buffer 缓冲区对象,用于数据消费。
     */
    public Consumer(Buffer buffer) {
        this.buffer = buffer;
    }

    /**
     * 重写run方法,定义消费者线程的执行逻辑。
     * 主要负责从缓冲区获取数据并打印,重复执行10次。
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            int val = 0;
            try {
                // 从缓冲区获取数据,如果被中断则抛出RuntimeException。
                val = buffer.pull();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 打印消费了的数据。
            System.out.println("消费了" + val);
        }
    }
}


/**
 * Buffer类用于实现一个固定大小的缓冲区。
 * 它使用队列来存储数据,并且支持线程安全的添加和提取数据操作。
 */
class Buffer {
    /**
     * 使用LinkedList作为队列实现,因为其在添加和删除操作上具有较好的性能。
     */
    private Queue<Integer> queue = new LinkedList<>();
    
    /**
     * 缓冲区的大小被固定为5,这个大小决定了可以存储的最大数据量。
     */
    private int size = 5;
    
    /**
     * 向缓冲区中添加一个数据项。
     * 如果缓冲区已满,则当前线程进入等待状态,直到缓冲区有空位。
     * 
     * @param val 要添加到缓冲区的值。
     * @throws InterruptedException 如果线程在等待时被中断。
     */
    public synchronized void add(int val) throws InterruptedException {
        // 如果队列已满,则等待直到有空间可用。
        if (queue.size() > size) {
            wait();
        }
        // 添加新值到队列。
        queue.add(val);
        // 唤醒其他等待的线程,可能有线程在等待消费数据。
        notify();
    }
    
    /**
     * 从缓冲区中提取一个数据项。
     * 如果缓冲区为空,则当前线程进入等待状态,直到有数据可用。
     * 
     * @return 从缓冲区中提取的数据项。
     * @throws InterruptedException 如果线程在等待时被中断。
     */
    public synchronized int pull() throws InterruptedException {
        // 如果队列为空,则等待直到有数据可用。
        if (queue.size() == 0) {
            wait();
        }
        // 提取并返回队列的第一个元素。
        int val = queue.poll();
        // 唤醒其他等待的线程,可能有线程在等待添加数据。
        notify();
        return val;
    }
}

标签:消费者,生产者,buffer,线程,缓冲区,设计模式,数据
From: https://www.cnblogs.com/jhhhred/p/18316903

相关文章

  • 职责链、命令和观察者设计模式的区别
    职责链、命令和观察者是三种不同的设计模式,它们各自解决不同类型的问题。下面分别介绍这三种设计模式的特点和区别:1.职责链模式(ChainofResponsibility)定义:职责链模式是一种行为设计模式,它通过将请求的处理者组织成一个链,使得请求可以沿这条链传递,直到有一个处理者处理......
  • 设计模式之观察者模式(学习笔记)
    定义观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会收到通知并自动更新。这种模式用于实现对象之间的解耦,使得一个对象的变化可以通知并更新多个依赖对象,而无需直接引用它们。为什么使用观察者模式?解耦观......
  • Linux C++ 065-设计模式之组合模式
    LinuxC++065-设计模式之组合模式本节关键字:Linux、C++、设计模式、组合模式相关库函数:概念组合模式(CompositePattern),又叫做部分-整体模式,使得用户对单个对象和组合对象的使用具有一致性。它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理......
  • Linux C++ 066-设计模式之访问者模式
    LinuxC++066-设计模式之访问者模式本节关键字:Linux、C++、设计模式、访问者模式相关库函数:概念在访问者模式(VisitorPattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模......
  • Perl中的设计模式革新:命令模式的实现与应用
    Perl中的设计模式革新:命令模式的实现与应用在面向对象编程中,设计模式是解决特定问题的成熟模板。命令模式作为行为设计模式之一,它将请求封装为对象,从而允许用户根据不同的请求对客户进行参数化。本文将深入探讨如何在Perl中实现命令模式,并提供详细的代码示例,帮助开发者在Pe......
  • 设计模式之行为型模式
    行为型模式关注流程控制。行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法完成的任务,涉及算法与对象间职责的分配。类行为模式:采用继承机制来在类间分派行为对象行为模式:采用组合或聚合在对象间分配行为行......
  • 第4章.消费者领域中的模式实现
            我们在前几章中学习了重要的建筑模式;本章介绍了与消费者领域相关的这些模式的用例。尽管消费者领域存在许多用例(电子健康、老年护理、宠物追踪、能源管理、安全保障、机器人吸尘器等),但本章仅详细介绍两个用例——家庭自动化和智能煮蛋器——以透视实施消费者物......
  • 单例设计模式
    单例设计模式:设计模式:​一个问题通常有n种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。​设计模式有23种,对应23种软件开发中会遇到的经典问题。单例设计模式:确保一个类只有一个对象。  饿汉式单例:饿汉式单例:拿对象时,对象......
  • 模板方法设计模式
    模板方法设计模式:模板方法设计模式:解决方法中存在重复代码的问题。  模板方法设计模式的写法:1、定义一个抽象类2、在里面定义2个方法​一个是模板方法:把相同代码放里面去​一个是抽象方法:具体实现交给子类完成建议使用final关键字修饰模板方法:​模板方......
  • 设计模式
    总的总结策略模式:注入接口观察者模式:事件与监听器责任链模式:方法三抽象类代理模式:aop适配器模式单例模式建造者模式@Builder工厂模式......