双非本科准备秋招(20.1)—— 并发编程之生产者消费者

生产者消费者

与保护性暂停中的不同,不需要产生结果和消费结果的线程一一对应

生产者仅负责产生结果数据,不关心数据该如何处理,而消费者专心处理结果数据

JDK 中各种阻塞队列,采用的就是这种模式

代码实现:

        首先,设计消息队列类MessageQueue,需要指定容量capacity,用双向链表list作为容器。

        提供take方法:检查list是否是空,空的话就wait,如果不空就打印Message,并唤醒所有线程。

        提供put方法:检查list是否满了,满了的话就wait,如果不满就添加Message,并唤醒所有线程。

        可以看到,以上的写法都是使用wait和notify的模板写法。

class MessageQueue{private LinkedList<Message> list = new LinkedList<>();private int capacity;public MessageQueue(int capacity) {this.capacity = capacity;}//取public Message take(){synchronized (list){while (list.isEmpty()){try {log.debug("队列空了");list.wait();} catch (InterruptedException e) {e.printStackTrace();}}Message message = list.removeFirst();log.debug("取出来了{}", message);list.notifyAll();return message;}}//存public void put(Message message){synchronized (list){while(list.size() == capacity){try {log.debug("队列满了");list.wait();} catch (InterruptedException e) {e.printStackTrace();}}list.addLast(message);log.debug("添加了{}", message);list.notifyAll();}}
}

        设计Message类,需要一个唯一标识id,还需要一个Object类型的value值。

final class Message{private int id;private Object value;public Message(int id, Object value) {this.id = id;this.value = value;}public int getId() {return id;}public Object getValue() {return value;}@Overridepublic String toString() {return "Message{" +"id=" + id +", value=" + value +'}';}
}

         完整代码:

public class ProductAndConsumer {public static void main(String[] args) {MessageQueue q = new MessageQueue(3);for (int i = 1; i <= 5; i++){//lambda表达式必须传final的值,不能变。int id = i;new Thread(()->{q.put(new Message(id, "v"+id));}, "生产者").start();}new Thread(()->{while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}Message t = q.take();}}, "消费者").start();}
}/*** 消息队列类*/
@Slf4j(topic = "c.test")
class MessageQueue{private LinkedList<Message> list = new LinkedList<>();private int capacity;public MessageQueue(int capacity) {this.capacity = capacity;}//取public Message take(){synchronized (list){while (list.isEmpty()){try {log.debug("队列空了");list.wait();} catch (InterruptedException e) {e.printStackTrace();}}Message message = list.removeFirst();log.debug("取出来了{}", message);list.notifyAll();return message;}}//存public void put(Message message){synchronized (list){while(list.size() == capacity){try {log.debug("队列满了");list.wait();} catch (InterruptedException e) {e.printStackTrace();}}list.addLast(message);log.debug("添加了{}", message);list.notifyAll();}}
}/*** Message对象,只有get方法,并且final不可继承,也不会被子类重写方法,很安全。*/
final class Message{private int id;private Object value;public Message(int id, Object value) {this.id = id;this.value = value;}public int getId() {return id;}public Object getValue() {return value;}@Overridepublic String toString() {return "Message{" +"id=" + id +", value=" + value +'}';}
}

 某次的运行结果

21:17:06 [生产者] c.test - 添加了Message{id=5, value=v5}
21:17:06 [生产者] c.test - 添加了Message{id=2, value=v2}
21:17:06 [生产者] c.test - 添加了Message{id=3, value=v3}
21:17:06 [生产者] c.test - 队列满了
21:17:06 [生产者] c.test - 队列满了
21:17:07 [消费者] c.test - 取出来了Message{id=5, value=v5}
21:17:07 [生产者] c.test - 添加了Message{id=1, value=v1}
21:17:07 [生产者] c.test - 队列满了
21:17:08 [消费者] c.test - 取出来了Message{id=2, value=v2}
21:17:08 [生产者] c.test - 添加了Message{id=4, value=v4}
21:17:09 [消费者] c.test - 取出来了Message{id=3, value=v3}
21:17:10 [消费者] c.test - 取出来了Message{id=1, value=v1}
21:17:11 [消费者] c.test - 取出来了Message{id=4, value=v4}
21:17:12 [消费者] c.test - 队列空了

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

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

相关文章

【开源】基于JAVA+Vue+SpringBoot的新能源电池回收系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回收机构模块2.4 电池订单模块2.5 客服咨询模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 E-R 图设计 四、系统展示五、核心代码5.1 增改电池类型5.2 查询电池品类5.3 查询电池回…

MySQL之密码策略和用户授权

华子目录 密码策略查看数据库当前的密码策略密码策略详解caching_sha2_password_auto_generate_rsa_keyscaching_sha2_password_digest_roundscaching_sha2_password_private_key_pathcaching_sha2_password_public_key_pathdefault_password_lifetimedisconnect_on_expired_pa…

Java学习笔记2024/2/7

练习四&#xff1a;复制数组 需求&#xff1a; 把一个数组中的元素复制到另一个新数组中去。 package com.angus.comprehensiveExercise; ​ public class test4 {public static void main(String[] args) {//需求&#xff1a;// 把一个数组中的元素复制到另一个新数组中去…

Excel——合并计算

1.表格的合并计算&#xff08;单张表格/多个表格&#xff09; Q&#xff1a;请统计两个表格中各商品的总销量和总销售额&#xff0c;将结果放置在下方任意位置。 A&#xff1a;选择一个需要将合并计算数据放置区域的空白单元格 选择【数据】——【合并计算】&#xff0c;【函…

秘塔科技推出AI搜索产品「秘塔AI搜索」

近日&#xff0c;国内一家人工智能科技公司&#xff08;秘塔科技&#xff09;推出了一款AI搜索产品——秘塔AI搜索&#xff0c;能够大幅提升搜索效率&#xff0c;解决日常生活、工作学习等场景中遇到的各类搜索需求。 秘塔AI搜索官网&#xff1a;https://metaso.cn/ 相较于传统…

前端文件下载的多种方式

前端文件下载的多种方式。 前言a标签下载a标签常用属性介绍- target&#xff0c;href&#xff0c;download。 window.location.href下载window.open下载iframe 下载动态生成a标签下载文件url下载文件流下载blob文件流转换常用类型 使用 streamSaver 看实时下载进度 前言 如果我…

B站UP主实时信息获取展示php源码

B站UP主实时数据展示系统 - PHP源码分享 想要实时追踪你心仪的B站UP主的最新动态吗&#xff1f;现在&#xff0c;你可以轻松获取并展示B站UP主的实时数据&#xff0c;包括粉丝数、作品数、头像、播放量等关键信息。 功能亮点&#xff1a; 实时更新&#xff1a;系统通过B站AP…

OpenCV识别视频中物体运动并截取保存

功能很简单&#xff1a;输入原始视频&#xff0c;输出视频中有画面变化的部分 适合理解基本框架&#xff0c;可以在这个基础上增加各种酷炫时髦的功能 [doge] ※注释非常保姆级※ import cv2 import numpy as np import os from datetime import datetime# 检测两帧之间变化…

航芯ACM32G103开发板评测 08 ADC Timer外设测试

航芯ACM32G103开发板评测 08 ADC Timer外设测试 1. 软硬件平台 ACM32G103 Board开发板MDK-ARM Keil 2. 定时器Timer 在一般的MCU芯片中&#xff0c;定时器这个外设资源是非常重要的&#xff0c;一般可以分为SysTick定时器&#xff08;系统滴答定时器&#xff09;、常规定时…

【洛谷 P1143】进制转换 题解(数学+除基取余法)

进制转换 题目描述 请你编一程序实现两种不同进制之间的数据转换。 输入格式 共三行&#xff0c;第一行是一个正整数&#xff0c;表示需要转换的数的进制 n ( 2 ≤ n ≤ 16 ) n\ (2\le n\le 16) n (2≤n≤16)&#xff0c;第二行是一个 n n n 进制数&#xff0c;若 n >…

【Django-ninja】在django ninja中处理异常

1. 直接抛内置异常 Django ninja内置了一些常用异常类。 from ninja.errors import HttpErrorapi.get("/some/resource") def some_operation(request):if True:raise HttpError(503, "Service Unavailable. Please retry later.")2. 覆写异常类 可以覆…

代码随想录算法训练营29期Day43|LeetCode 1049,494,474

文档讲解&#xff1a;最后一块石头的重量II 目标和 一和零 1049.最后一块石头的重量II 题目链接&#xff1a;https://leetcode.cn/problems/last-stone-weight-ii/description/ 思路&#xff1a; 本题其实就是尽量让石头分成重量相同的两堆&#xff0c;相撞之后剩下的石头最…

CTF秀 ctfshow WEB入门 web1-10 wp精讲

目录 web1_查看源码 web3_抓包 web4-9_目录文件 web10_cookie web1_查看源码 ctrlu 查看源码 web3_抓包 查看源码&#xff0c;无果 抓包&#xff0c;找到flag web4-9_目录文件 GitHub - maurosoria/dirsearch: Web path scanner 下载dirsearch工具扫一下就都出来了 web4-…

以“防方视角”观JS文件信息泄露

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 案例概述02 攻击路径03 防方思路 01 案例概述 这篇文章来自微信公众号“黑白之道”&#xff0c;记录的某师傅从js文件泄露接口信息&#xff0c;未授权获取大量敏感信息以及通过逻辑漏洞登录管理员账…

邦芒解析:跳槽到管理职位须分析的四点

如果跳槽到一般的管理职位&#xff0c;需要应聘者至少进行四方面的分析&#xff1a; ​一、自己实际的背景。包括应聘者所从事的行业、专业是什么&#xff1f;实际工作年限是多少、积攒了什么样的经验、已取得的业绩等&#xff1b; ​二、自己真实的能力。除了有好的业绩…

chagpt的原理详解

GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种基于Transformer架构的生成式预训练模型。GPT-3是其中的第三代&#xff0c;由OpenAI开发。下面是GPT的基本原理&#xff1a; Transformer架构&#xff1a; GPT基于Transformer架构&#xff0c;该架构由Att…

Vue中路由守卫的详细应用

作为一名web前端开发者&#xff0c;我们肯定经常使用Vue框架来构建我们的项目。而在Vue中&#xff0c;路由是非常重要的一部分&#xff0c;它能够实现页面的跳转和导航&#xff0c;提供更好的用户体验。然而&#xff0c;有时我们需要在路由跳转前或跳转后执行一些特定的逻辑&am…

C语言中的条件编译:探索编译时的决策

在C语言中&#xff0c;条件编译是一种特殊的编译技术&#xff0c;它允许开发者在编译时根据特定的条件选择性地包含或排除代码片段。这种技术非常有用&#xff0c;特别是当你想针对不同的平台、操作系统或配置编译不同的代码时。 在C语言中&#xff0c;条件编译主要通过预处理…

go语言进阶篇——面向对象(一)

什么是面向对象 在我们设计代码时&#xff0c;比如写一个算法题或者写一个问题结局办法时&#xff0c;我们常常会使用面向过程的方式来书写代码&#xff0c;面向过程主要指的是以解决问题为中心&#xff0c;按照一步步具体的步骤来编写代码或者调用函数&#xff0c;他在问题规…

后端的技术设计文档

一、 背景 1.简介 2.业务规划(非必需) 3.工作项拆解 拆解成多个工作项&#xff0c;每个工作项&#xff0c;需要多少人力。 4.资源评估(非必需) 有没有新的服务 二、架构设计 1.架构图(非必需&#xff0c;新服务比较需要) 2.技术选型 SpringCloud、Redis、Mysql、Myba…