線程間的協作(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.pswp.cn/news/278049.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/278049.shtml
英文地址,請注明出處:http://en.pswp.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;深層網…

js閉包

閉包(closure)是Javacript語言的一個難點&#xff0c;也是它的特色&#xff0c;很多高級應用都要依靠閉包實現。 一、變量的作用域 要理解閉包&#xff0c;首先必須理解Javascript特殊的變量作用域。 變量的作用域無非就是兩種&#xff1a;全局變量和局部變量。 Javascript語言…

Teams的MessageExtension最新功能:Initiate actions

官方文檔到目前為止對這個initiate action的說明比較簡潔&#xff0c;由于沒有一步步的截圖和說明&#xff0c;從頭到尾看一遍可能還在云里霧里。 我一步步摸索著走了一遍&#xff0c;發現這個initiate action的功能如此強大&#xff0c;不敢獨享&#xff0c;所以寫此博文&…

Java枚舉根據key獲取value

package com.utcip.crm.common.constants; import com.utcip.crm.common.base.process.ScheduleStatusEnum; /** * 合同變更存儲mongodb 狀態值 * author jingfangnan * */ public enum ConstractMongoStatus { NEW(3,"新增"), UPDATE(2,"修改"), D…

Selenium-基礎操作

一、測試代碼 Test public void test() { WebDriver driver new FirefoxDriver(); // 打開當前包中的index頁面 driver.get("file:///D:/%E8%B5%B5%E6%AC%A2/Selenium/Selenium/src/com/html/index.html"); WaitSeconds(1000); // 清除用戶輸入 driver.findElement(…

開發針對特殊租戶的Teams機器人

有些朋友問到&#xff0c;如果想要開發一個bot針對于Teams的某些租戶&#xff0c;如何做&#xff1f;實際上微軟的Teams的SDK早就提供了類似的功能。 如果你使用的是Javascript/Node.JS開發&#xff0c;使用session.message.sourceEvent.tenant.id 就可以知道當前消息來自于哪…

行業看點 | 英特爾成功開發超導量子計算芯片 推動產業加速發展

量子計算將會成為下一次技術革命的核心&#xff0c;你可能認為它還很遙遠&#xff0c;實際上量子計算會比預料的來得早。近期&#xff0c;英特爾在量子芯片方面取得突破&#xff0c;讓量子計算朝著現實前進了一大步。 繼IBM公司發布了自主量子處理器&#xff0c;谷歌著手研究基…

Teams App抽獎機器人 - 基礎架構

今天我們來聊一下&#xff0c;一個Teams app的infrastructure&#xff0c;我在考慮LuckyDraw的主要出于這么幾個出發點&#xff1a; 可管理性。因為這是一個個人產品&#xff0c;以后維護工作也只有我一個人&#xff0c;所以我希望整個infrastructure簡單、易管理&#xff0c;不…

Teams Bot的ServiceLevel測試

每一個Teams bot實際上就是一個web api服務&#xff0c;這個服務通過Bot Framework和Teams進行通訊&#xff0c;所以對于Teams app的測試就是對于一個api service的測試。 軟件行業發展到如今&#xff0c;測試技術已經趨于成熟。單元測試&#xff0c;冒煙測試&#xff0c;整合…

BZOJ1016:[JSOI2008]最小生成樹計數——題解

https://www.lydsy.com/JudgeOnline/problem.php?id1016 現在給出了一個簡單無向加權圖。你不滿足于求出這個圖的最小生成樹&#xff0c;而希望知道這個圖中有多少個不同的最小生成樹。&#xff08;如果兩顆最小生成樹中至少有一條邊不同&#xff0c;則這兩個最小生成樹就是不…

如何做Teams Bot的測試覆蓋

在我昨天的文章中介紹了如果對Teams bot做service level的測試&#xff0c;那到底要寫多少的測試代碼才算夠&#xff1f;如何才算測試到位了&#xff1f;這個時候我們就需要用”測試覆蓋率”來衡量&#xff0c;雖然覆蓋率高并不一定代表著就可以高枕無憂的以為我們軟件質量高了…

Spring Boot開發MongoDB應用實踐

本文繼續上一篇定時任務中提到的郵件服務&#xff0c;簡單講解Spring Boot中如何使用MongoDB進行應用開發。 上文中提到的這個簡易郵件系統大致設計思路如下&#xff1a; 1、發送郵件支持同步和異步發送兩種 2、郵件使用MongDB進行持久化保存 3、異步發送&#xff0c;直接將郵件…

Teams Bot如何做全球化

Office365在全球有大量的用戶&#xff0c;可以說是擁有最多用戶的商業SaaS平臺。Teams最近在發展迅猛&#xff0c;有1300萬日活用戶&#xff0c;已經超越了Slack。? Microsoft Teams overtakes Slack with 13 million daily users 我在設計Teams LuckyDraw bot的時候就希望我…

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…

修改oracle 管理員密碼 cmd

1.sqlplus/nolog 2.conn / as sysdba 3.alter user 用戶名 identified by 新密碼;轉載于:https://www.cnblogs.com/taoqidexiaomao/p/9006927.html

在2019年6月Teams Community Call上分享的Teams app基礎架構視頻

我在2019年6月Teams Community Call(China)上分享的如何在azure上搭建典型的teams bot的基礎架構 會議視頻&#xff1a; 15:00 - 33:00 Download Video

解決 spring-cloud-starter-zipkin 啟動錯誤

應用場景&#xff1a;Spring Boot 服務添加 Zipkin 依賴&#xff0c;進行服務調用的數據采集&#xff0c;然后進行 Zipkin-Server 服務調用追蹤顯示。 示例pom.xml配置&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId>s…