线程间的协作(2)——生产者与消费者模式

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1.何为生产者与消费者

    在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。


import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;/*** @ClassName:Restraurant* @Description:何为生产者与消费者* @author: * @date:2018年5月3日*/
public class Restraurant {Meal m=null;Chef chef=new Chef(this);WaitPerson wait=new WaitPerson(this);ExecutorService service=Executors.newCachedThreadPool();public Restraurant() {service.execute(chef);service.execute(wait);}public static void main(String[] args) {new Restraurant();}
}
/*** @ClassName:Meal* @Description:生产者生成的数据* @author: * @date:2018年5月3日*/
class Meal{private final int orderNum;//食物订单编号public Meal(int num){orderNum=num;}public String toString(){return "Meal"+orderNum;}
}
/*** @ClassName:Chef* @Description:厨师类,及生产者* @author: * @date:2018年5月3日*/
class Chef implements Runnable{Restraurant r;int count=0;public Chef(Restraurant r) {this.r=r;}@Overridepublic void run() {try{while(!Thread.interrupted()){synchronized (this) {while(r.m!=null){System.out.println("厨师等待中");wait();//等待服务员取餐}}if(count++==10){System.out.println("今日已售完");r.service.shutdownNow();}System.out.println("订单完成,服务员取餐");synchronized (r.wait) {r.m=new Meal(count);r.wait.notifyAll();}TimeUnit.SECONDS.sleep(1);}}catch (InterruptedException e) {System.out.println("生产者线程强制中断");}}
}
/*** @ClassName:WaitPerson* @Description:服务员类,即消费者* @author: * @date:2018年5月3日*/
class WaitPerson implements Runnable{Restraurant r;public WaitPerson(Restraurant r) {this.r=r;}@Overridepublic void run() {try {while (!Thread.interrupted()) {synchronized (this) {while (r.m == null) {System.out.println("服务员等待中");wait();// 等待厨师生成食物}}System.out.println("服务员以取餐" + r.m);synchronized (r.chef) {r.m = null;r.chef.notifyAll();}}} catch (InterruptedException e) {System.out.println("消费者线程强制中断");}}}

2.生产者与消费者模式

    1)产生原因:在多线程开发 中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理 完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须 等待生产者。wait与notify方法以一种非常低级的方式解决了任务互相通知的问题,即每次交互都要进行一次握手,极大影响的效率以及性能,为了解决这种生产消费能力不均衡的问题,便有了生产者和消费者模式。

    2)原理:生产者和消费者模式是通过一个容器(比如同步阻塞队列)来解决生产者和消费者的强耦合问题。生产者和消 费者彼此之间不直接通信,而是通过阻塞队列来进行通信,所以生产者生产完数据之后不用 等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取, 阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。 这个阻塞队列就是用来给生产者和消费者解耦的。java.util.concurrent.BlockingQueue接口提供了这个队列,通常使用其实现子类ArrayBlockingQueue,LinkedBlockingQueue。当消费者任务试图从同步队列中获取对象,如果队列为空时,那么队列则会挂起消费者任务,并且当拥有足够多的元素可用时才会恢复消费者任务。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;public class UseBlockingQueue {public static void main(String[] args) throws InterruptedException {LinkedBlockingQueue<Toast> dry=new LinkedBlockingQueue<Toast>(),butter=new LinkedBlockingQueue<Toast>(),jam=new LinkedBlockingQueue<Toast>(),con=new LinkedBlockingQueue<Toast>();ExecutorService exec=Executors.newCachedThreadPool();exec.execute(new MakeToast(dry));//制作初始吐司任务exec.execute(new Butter(dry,butter));//吐司抹黄油任务exec.execute(new Jam(butter,jam));//吐司抹果酱任务exec.execute(new Consumer(jam));//消费者任务,食用吐司TimeUnit.SECONDS.sleep(5);exec.shutdownNow();}
}
class Toast{private int status;//吐司状态:0代表制作吐司,1代表抹黄油,2代表向抹了黄油的吐司抹果酱private final int id;public Toast(int id1) {id=id1;}public void butter(){status=1;};public void jam(){status=2;}public int getStatus(){return status;}public int getId(){return id;}public String toString(){return "toast "+id+":"+status;}
}
/*** @Description:制作初始吐司*/
class MakeToast implements Runnable{private LinkedBlockingQueue<Toast> queue=new LinkedBlockingQueue<Toast>();private int count=0;public MakeToast(LinkedBlockingQueue<Toast> q) {queue=q;}@Overridepublic void run() {try{while(!Thread.interrupted()){Thread.sleep(1000);//制作时间Toast t=new Toast(count);System.out.println(t);queue.put(t);//添加到同步队列count++;}}catch (InterruptedException e) {System.out.println("make process interrupted");}System.out.println("make process off");}
}
/*** @Description:涂抹黄油*/
class Butter implements Runnable{private LinkedBlockingQueue<Toast> queue1,queue2;//未加料吐司队列,抹黄油后吐司队列public Butter(LinkedBlockingQueue<Toast> q1,LinkedBlockingQueue<Toast>q2) {queue1=q1;queue2=q2;}@Overridepublic void run() {try{while(!Thread.interrupted()){Toast t=queue1.take();//如果队列中没有可用元素将会阻塞,直至有可用元素被添加t.butter();System.out.println(t);queue2.put(t);}}catch (InterruptedException e) {System.out.println("butter process interrupted");}System.out.println("butter process off");}
}
/*** @Description:涂抹果酱*/
class Jam implements Runnable{private LinkedBlockingQueue<Toast> queue1,queue2;//抹黄油后吐司队列,抹果酱吐司队列public Jam(LinkedBlockingQueue<Toast> q1,LinkedBlockingQueue<Toast>q2) {queue1=q1;queue2=q2;}@Overridepublic void run() {try{while(!Thread.interrupted()){Toast t=queue1.take();//如果队列中没有可用元素将会阻塞,直至有可用元素被添加t.jam();System.out.println(t);queue2.put(t);}}catch (InterruptedException e) {System.out.println("jam process interrupted");}System.out.println("jam process off");}
}
/*** @Description:被食用*/
class Consumer implements Runnable{private LinkedBlockingQueue<Toast> finished;//抹黄油后吐司队列,抹果酱吐司队列int count=0;public Consumer(LinkedBlockingQueue<Toast> q) {finished=q;}@Overridepublic void run() {try{while(!Thread.interrupted()){Toast t=finished.take();//如果队列中没有可用元素将会阻塞,直至有可用元素被添加if(t.getId()!=count++||t.getStatus()!=2){System.out.println("过程出现错误");return;}else{System.out.println("所有过程正确实现"+"toast "+t.getId()+"被食用");}}}catch (InterruptedException e) {System.out.println("eat process interrupted");}System.out.println("eat process off");}
}

 

转载于:https://my.oschina.net/ProgramerLife/blog/1806314

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

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

相关文章

一位面试者提到直接调用vuex中mutations方法

简述是用this.$store.mutations.xxx(xx)方式调用&#xff0c;因从未见过此种调用方式&#xff0c;回来就搜索了一下&#xff0c;查询结果如下 首先前文&#xff1a; 获取 state 的方式有两种&#xff0c;分别是 this.$store.state.num 这种直接获取的方式&#xff0c;以及通过 …

从无到有到完善 - Teams抽奖机器人开发历程

我没有写博客有2&#xff0c;3个月了&#xff0c;好几个朋友来问我怎么不继续了。实际上这几个月我受到微软好友的鼓舞和鼓励&#xff0c;再加上今年2月1日有幸成为了微软中国区第一位Teams的MVP&#xff0c;所以决定不再停留于技术demo&#xff0c;而是使用微软最新的技术开发…

残差网络

作用&#xff1a;使得深层网络可以获得更好的性能&#xff0c;没有它&#xff0c;即使加深网络的层数无法直接获得性能的提升。 我的理解&#xff1a;1、使得低层的特征表示可以越层传递。 2、在反向传播时LOSS可以直接训练低层特征。 3、浅层网络的恒等映射&#xff0c;深层网…

Teams的MessageExtension最新功能:Initiate actions

官方文档到目前为止对这个initiate action的说明比较简洁&#xff0c;由于没有一步步的截图和说明&#xff0c;从头到尾看一遍可能还在云里雾里。 我一步步摸索着走了一遍&#xff0c;发现这个initiate action的功能如此强大&#xff0c;不敢独享&#xff0c;所以写此博文&…

Teams App抽奖机器人 - 基础架构

今天我们来聊一下&#xff0c;一个Teams app的infrastructure&#xff0c;我在考虑LuckyDraw的主要出于这么几个出发点&#xff1a; 可管理性。因为这是一个个人产品&#xff0c;以后维护工作也只有我一个人&#xff0c;所以我希望整个infrastructure简单、易管理&#xff0c;不…

如何做Teams Bot的测试覆盖

在我昨天的文章中介绍了如果对Teams bot做service level的测试&#xff0c;那到底要写多少的测试代码才算够&#xff1f;如何才算测试到位了&#xff1f;这个时候我们就需要用”测试覆盖率”来衡量&#xff0c;虽然覆盖率高并不一定代表着就可以高枕无忧的以为我们软件质量高了…

Spring Boot开发MongoDB应用实践

本文继续上一篇定时任务中提到的邮件服务&#xff0c;简单讲解Spring Boot中如何使用MongoDB进行应用开发。 上文中提到的这个简易邮件系统大致设计思路如下&#xff1a; 1、发送邮件支持同步和异步发送两种 2、邮件使用MongDB进行持久化保存 3、异步发送&#xff0c;直接将邮件…

QuickBI助你成为分析师-邮件定时推送

创建报表过程中经常需要将报表情况定时推送给其他用户&#xff0c;及时了解数据情况。高级版本邮件推送功能支持仪表板周期性推送到订阅人&#xff0c;默认以当前登录者视角查看&#xff0c;同时支持结合 行级权限进行权限控制 和 结合全局参数功能确定邮件推送内容参数&#x…

2019年5月 Teams Community Call (China)

这个月有四个话题&#xff1a; Tony Xia&#xff1a;这个月的Teams的产品更新&#xff0c;Teams开发能力的更新&#xff0c;开源项目更新&#xff0c;库更新王远&#xff1a;升级/迁移到Microsoft Teams刘钰&#xff1a;Teams账号注册探索指南Paul Zhang/Cheung&#xff1a;Bu…

在2019年6月Teams Community Call上分享的Teams app基础架构视频

我在2019年6月Teams Community Call(China)上分享的如何在azure上搭建典型的teams bot的基础架构 会议视频&#xff1a; 15:00 - 33:00 Download Video

什么是Microsoft Teams的App Studio

Teams的app studio很多用户可能不知道&#xff0c;但是对于一个teams平台的开发人员来说&#xff0c;这个是开发利器&#xff0c;利用这个工具你可以轻松的配置manifest文件&#xff0c;可以轻松的一站式创建teams app所需要的所有东西。而且你可以很方便的可视化配置adaptive …

如何使用ARM创建Teams Bot所需要的Azure资源

相信很多devops已经全面开始使用ARM来创建azure资源了&#xff0c;ARM有很多方便的地方&#xff0c;比如简单易学&#xff0c;Infrastructure as Code&#xff0c;但是深入使用ARM开始会发现一些有待改进的方面。这篇文章主要是分享一下我在做Teams app的时候使用ARM来创建资源…

Bot Service自带的数据分析统计功能

每个产品上线后都希望自己能实时看到多少用户在使用我的产品&#xff0c;我的服务&#xff0c;有多少使用量&#xff0c;有没有遇到问题。市面上做用户数据、行为分析的公司也不少&#xff0c;但是大多数都需要我们修改一些代码来集成第三方的sdk库。 我的teams app上线后也急…

图灵社区 和 大家网

http://www.ituring.com.cn/ http://club.topsage.com/ 大家论坛 http://www.topsage.com/ http://www.dxbbba.com/ 大学生必备吧 转载于:https://www.cnblogs.com/onelikeone/p/9023267.html

Teams内嵌的卡片image的限制

我的LuckyDraw上线后收到了不少有价值的反馈&#xff0c;其中有一部分是针对图片的&#xff0c;有一些用户说他们填写了image的url&#xff0c;但是图片显示不出来。 实际上这个问题在我提交这个应用到微软审核团队的时候&#xff0c;审核团队也提出了类似问题。但这个是Teams本…

Teams的Incoming Webhook

我在去年的一篇文章里介绍过Teams的outgoing webhook&#xff0c;这个可以用来实现一个简单的用户和service对话机制。 Teams除了outgoing webhook以外&#xff0c;还有一个incoming webhook&#xff0c;从名字上我们也可以立刻知道&#xff0c;这个webhook是用来处理进入Team…

Comet OJ - Contest #0题解

传送门 菜爆了……总共只有一道题会做的……而且也没有短裙好难过 为啥必须得有手机才能注册账号啊喂……歧视么…… \(A\) 解方程 推一下柿子大概就是 \[x-\sqrt{n}yz2\sqrt{yz}\] 如果\(\sqrt{n}\)是无理数&#xff0c;那么就是 \[xyz,{n\over 4}yz\] 那么要满足\(n\)必须是\…

tornado 08 数据库-ORM-SQLAlchemy-表关系和简单登录注册

tornado 08 数据库-ORM-SQLAlchemy-表关系和简单登录注册 引言 #在数据库&#xff0c;所谓表关系&#xff0c;只是人为认为的添加上去的表与表之间的关系&#xff0c;只是逻辑上认为的关系&#xff0c;实际上数据库里面的表之间并没有所谓的表关系 一、一对一表关系 Module #需…

白白的(baibaide)

白白的&#xff08;baibaide&#xff09; 有一个长度为 $n$ 的序列 $a_1, a_2, \dots, a_n$&#xff0c;一开始每个位置都是白色。如果一个区间中每个位置都是白色&#xff0c;则称这是一个白白的区间。如果一个白白的区间向左或向右延长后都不是白白的区间了&#xff0c;则称这…

使用Adaptive cards来构建Teams app的界面

Teams app的task module十分好用&#xff0c;当用户点击了一个卡片上的按钮是可以在Teams里弹出一个对话框&#xff0c;对话框的内容可以是开发人员自己的一个网页页面&#xff0c;或者是adaptive card。 在我的LuckyDraw bot里&#xff0c;我比较了这两种的优势和劣势&#xf…