Java并发-生产者消费者实现

news2025/2/2 15:24:21

生产者与消费者模型介绍

定义: 生产者消费者模式是一个十分经典的多线程并发协作的模式。

意义:弄懂生产者消费者问题能够让我们对并发编程的理解加深。

介绍:所谓生产者 - 消费者问题,实际上主要是包含了两类线程,一种是生产者线程用于生产数据,另一种是消费者线程用于消费数据,为了解耦生产者和消费者的关系,通常会采用共享的数据区域。

共享的数据区域就像是一个仓库,生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为。而消费者只需要从共享数据区中去获取数据,就不再需要关心生产者的行为。

生产者与消费者实现

场景设计

  • 创建一个工厂类 ProductFactory,该类包含两个方法,produce 生产方法和 consume 消费方法;
  • 对于 produce 方法,当没有库存或者库存达到 10 时,停止生产。为了更便于观察结果,每生产一个产品,sleep 3秒;
  • 对于 consume 方法,只要有库存就进行消费。为了更便于观察结果,每消费一个产品,sleep 3秒;
  • 库存使用 LinkedList 进行实现,此时 LinkedList 即共享数据内存
  • 创建一个 Producer 生产者类,用于调用 ProductFactory 的 produce 方法。生产过程中,要对每个产品从 0 开始进行编号;
  • 创建一个 Consumer 消费者类,用于调用 ProductFactory 的 consume 方法;
  • 创建一个测试类,main 函数中创建 2 个生产者和 3 个消费者,运行程序进行结果观察。

ProductFactory.class

package jvm.juc.proAndcom;

import java.util.LinkedList;

public class ProductFactory {
    private  volatile LinkedList<String> products; //根据需求定义库存,用 LinkedList 实现
    private int capacity = 10; // 根据需求:定义最大库存 10
    public ProductFactory() {
        products = new LinkedList<String>();
    }
    // 根据需求:produce 方法创建
    public synchronized void produce(String product) {
        while (capacity == products.size()) { //根据需求:如果达到 10 库存,停止生产
            try {
                System.out.println("警告:线程("+Thread.currentThread().getName() + ")准备生产产品,但产品池已满");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        products.add(product); //如果没有到 10 库存,进行产品添加
        try {
            Thread.sleep(1000); //根据需求为了便于观察结果,每生产一个产品,sleep 5000 ms
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程("+Thread.currentThread().getName() + ")生产了一件产品:" + product+";当前剩余商品"+products.size()+"个");
        notify(); //生产了产品,通知消费者线程从 wait 状态唤醒,进行消费
    }

    // 根据需求:consume 方法创建
    public synchronized String consume() {
        while (products.size()==0) { //根据需求:没有库存消费者进入wait状态
            try {
                System.out.println("警告:线程("+Thread.currentThread().getName() + ")准备消费产品,但当前没有产品");
                wait(); //库存为 0 ,无法消费,进入 wait ,等待生产者线程唤醒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        String product = products.remove(0) ; //如果有库存则消费,并移除消费掉的产品
        try {
            Thread.sleep(1000);//根据需求为了便于观察结果,每消费一个产品,sleep 5000 ms
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程("+Thread.currentThread().getName() + ")消费了一件产品:" + product+";当前剩余商品"+products.size()+"个");
        notify();// 通知生产者继续生产
        return product;
    }
}

Consumer.Class

package jvm.juc.proAndcom;

public class Consumer implements Runnable{

    private ProductFactory factory;

    public Consumer(ProductFactory productFactory) {
        factory = productFactory;
    }

    @Override
    public void run() {
        while (true) {
            String consume = factory.consume();
        }
    }
}

Producer.class

package jvm.juc.proAndcom;

public class Producer implements Runnable{
    private ProductFactory factory;
    public Producer(ProductFactory productFactory) {
        this.factory = productFactory;
    }

    @Override
    public void run() {
        int i = 0;
        while (true) {
            factory.produce(String.valueOf(i));
            i++;
        }
    }
}

Test.class

package jvm.juc.proAndcom;

import internet.c1.Factory;

public class Test extends Thread{
    public static void main(String[] args) {
        ProductFactory factory = new ProductFactory();
        new Thread(new Producer(factory),"一号生产者").start();
        new Thread(new Producer(factory),"二号生产者").start();
        new Thread(new Consumer(factory),"一号消费者").start();
        new Thread(new Consumer(factory),"二号消费者").start();
        new Thread(new Consumer(factory),"三号消费者").start();

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/40461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python面向对象编程之对象行为与特殊方法

面向对象编程之对象行为与特殊方法 python中的对象通常根据它们的行为和实现的功能进行分类。例如&#xff0c;所有序列类型都分在一组&#xff0c;如字符串&#xff0c;列表和元组&#xff0c;就是因为它们都支持一组相同的序列操作&#xff0c;如s[n], len[s]等。 所有基本…

【学习总结】LSD-SLAM配置与运行记录

今天安装测试了LSD-SLAM&#xff0c;记录配置中遇到的问题。 LSD-SLAM论文 LSD-SLAM: Large-Scale Direct Monocular SLAM, J. Engel, T. Schps, D. Cremers, ECCV 14 Semi-Dense Visual Odometry for a Monocular Camera, J. Engel, J. Sturm, D. Cremers, ICCV 13 配置环境…

SpringBoot实现多数据源(四)【集成多个 Mybatis 框架】

上一篇文章《SpringBoot实现多数据源&#xff08;三&#xff09;【AOP 自定义注解】》 四、集成多个 Mybatis 框架 实现步骤 创建一个 dynamic_mybatis 的springboot项目&#xff0c;导入依赖 pom.xml <dependencies><!--jdbc--><dependency><groupId…

Fiddler抓取手机app包

文章目录1. 配置fiddler1.1 下载fiddler1.2 配置fiddler2. 安装证书2.1 查询主机ip2.2下载证书2.3 手机安装证书2.4 查询安装的证书3. 手机设置代理4. 测试是否抓包成功大前提&#xff1a;手机和Fiddler所在的主机在同一网段&#xff0c;且能够互相访问 1. 配置fiddler 1.1 下…

第三十八篇 Vue中封装Swiper组件 2.0

上一篇内容讲到封装Swiper组件的一个过程&#xff0c;如果是静态的数据封装组件初始化在mounted当中并无多大影响&#xff0c;但是这样封装的组件复用性较低或者可能只使用一次&#xff0c;那么在动态使用通过ajax请求数据需要面临的是swiper初始化过早的问题&#xff0c;在mou…

【车间调度】基于matlab混合蛙跳算法 (SFLA) 求解简单调度问题【含Matlab源码 2247期】

⛄一、车间调度简介 在传统的SFLA中&#xff0c;每一个青蛙的位置代表一个解&#xff0c;若干个青蛙组成的种群代表一个解的集合&#xff0c;种群被划分为不同的组&#xff0c;即模因组&#xff0c;对每个模因组执行搜索过程&#xff0c;当达到终止条件后&#xff0c;重新将模…

编译原理13:SLR(1)分析表、LR(1)分析表

更强的LR分析 可以根据当前单词&#xff0c;来选择是移进还是归约。只要所有移进项目中的点后面的那些终结符&#xff0c;与归约项目生成的非终结符的Follow集合的元素没有重叠。若当前单词属于上述Follow集合里则规约 SLR(1)冲突解决办法 SLR(1)分析表的构造 SLR(1)分析表的构…

001. 组合

1.题目链接&#xff1a; 77. 组合 2.大概思路&#xff1a; 2.1题目要求&#xff1a; 给两个值 n 和 k &#xff0c;要求从[1&#xff0c;n]的区间中&#xff0c;输出所有元素数量为k的组合。&#xff08;不能有[1,1]&#xff0c;值只能取一次&#xff09; 2.2思路&#xff…

(十七)Spring6整合JUnit

文章目录环境Spring对JUnit4的支持Spring对JUnit5的支持上一篇&#xff1a;&#xff08;十六&#xff09;Spring对事务的支持 环境 spring6里程碑版本的仓库 依赖&#xff1a;spring context依赖、spring对junit的支持相关依赖、junit4依赖、junit5依赖 <!--配置多个仓库-…

Spring【Spring的创建与使用】

Spring【Spring的创建项目与使用】&#x1f34e;一.Spring创建项目&#x1f352;1.1 创建⼀个 Maven 项⽬&#x1f352;1.2 添加 Spring 框架⽀持&#x1f352;1.3 添加启动类&#x1f34e;二.Bean对象的存储与获取&#x1f352;2.1 存储 Bean 对象&#x1f349; 2.1.1 创建 Be…

C语言【微项目19】—大整数字符串乘法器[纯字符串乘法][乘法表与加法表]【2022-11-27】

C语言【微项目19】—大整数字符串乘法器[纯字符串乘法][乘法表与加法表]【2022-11-27】1.函数功能2 简要测试结果3.BigInterNoLimitMutiString.c3.大整数字符串乘法器实现思路4. 大整数字符串乘法器典型使用流程main.c【TDTX】 【C99】 【编译与运行环境】64位Windows操作系统&…

Unity嵌入Android项目开发

目录前言1 搭建开发环境2 创建Unity项目2.1 新建项目2.2 Unity构建配置2.3 Android环境相关配置2.4 导出Unity库文件3 创建Android项目3.1 新建Android项目3.2 Android环境相关配置3.2 导入Unity相关的库3.3 Android中跳转到Unity视图4 进阶扩展4.1 包体积优化4.1.1 mono和IL2C…

ILRuntime1.安装

目录 1&#xff1a;官网地址&#xff1a;介绍 — ILRuntime 2&#xff1a;注意事项&#xff1a; 3&#xff1a;安装 此文章是参照官方文档&#xff0c;自己的开发笔记。 1&#xff1a;官网地址&#xff1a;介绍 — ILRuntime 官方Unity示例代码&#xff1a;GitHub - Ourpa…

CUDA-矩阵乘2

这里从一个 cuda 初学者的角度来阐述如何优化一个形状较大的正方形乘正方形的 FP32 矩阵乘。 矩阵乘作为目前神经网络计算中占比最大的一个部分&#xff0c;其快慢会显著影响神经网络的训练与推断所消耗的时间。虽然现在市面上已经有非常多的矩阵乘的高效实现——如基于 cpu 的…

基于Pytorch框架的轻量级卷积神经网络垃圾分类识别系统

在我之前的博文中也写过一篇关于垃圾识别的文章&#xff0c;主要是基于tensorflow和keras实现的&#xff0c;数据集是一个比赛提供的&#xff0c;有40个细分的子类别&#xff0c;最近是在学习PyTorch框架&#xff0c;实践做项目的过程中就想拿垃圾识别的数据集再开发垃圾识别模…

物联网-常见的服务架构演变

常见的服务架构演变 背景 在互联网的发展中&#xff0c;后端的web服务也经历了很多的演变&#xff1b;在公司业务稍微简单的时候&#xff0c;采用简单的服务&#xff0c;可以提高开发效率&#xff0c;可以帮忙节省更多的成本。但随着用户数量的剧增&#xff0c;流量突增&…

keras-yolo3-master 项目实战cookbook

1、.h5文件转化 1.1 Error: FileNotFoundError: [Errno 2] No such file or directory: ‘yolov3.weights’ 解决办法&#xff1a;通过在.py文件中添加print()命令发现文件的打开路径有问题&#xff0c;因此在代码中手动添加.weights的绝对路径&#xff0c;使程序能够找到该文…

java.lang.reflect.Field 解读

java.lang.reflect.Field Java 中 Field 提供有关类或接口的单个字段的信息&#xff0c;以及对它的动态访问权限。反射的字段可能是一个类字段或实例字段。Field 是成员变量的意思。Field 也是一个类&#xff0c;该类位于 java.lang.reflect 包下。 https://docs.oracle.com/…

每天五分钟机器学习:支持向量机损失函数和互熵损失函数

本文重点 本节课程我们讲学习两个常见的损失函数,一个是支持向量机损失,也叫做hinge loss,另外一个损失函数是互熵损失函数,它常常应用于softmax分类器中。 hinge loss 单样本的hinge loss可以为: 这个意思是说样本分类错误的分数-样本分类正确的分数小于阈值▲,则损…

Spring Boot 2.7.6 正式版发布, SpringBoot 2.7.6来了

一、发布说明 11 月 25 日官方发布了 Spring Boot 2.7.6 版本&#xff0c;此版本包括 44 个错误修复、文档改进和依赖项升级。 二、更新内容 2.1 bug 修复 即使未启用基于注释的计划&#xff0c;ScheduledBeanLazyInitializationExcludeFilter 也会自动配置使用 ContextHi…