(四)生产者消费者模式
(一)生产者消费者模式原理:
在一个系统中,存在生产者和消费者两种角色,他们通过内存缓冲区进行通信,生产者生产消费者需要的资料,消费者把资料做成产品。生产消费者模式如下图:
(二)代码实现
生产者是一堆线程,消费者是另一堆线程,内存缓冲区可以使用List数组队列,数据类型只需要定义一个简单的类就好。最关键就是内存缓冲区为空的时候消费者必须等待,而内存缓冲区满的时候,生产者必须等待。其他时候可以是个动态平衡:
首先设置Market类:
其中变量有:Max(仓库最大值),List(用于存放数据)
方法有Producer(生产方法),Cost(消费方法)
public class Market{private int Max=20;private List<String>list=new ArrayList<String>();public synchronized void producer()throws InterruptedException{ //设置锁if(list.size()>=20){this.wait(): //超过容量时,等待}System.out.println("***开始生产,现在数量为"+list.size()); list.add("a");System.out.println("***生产后数量为"+list.size());this.notify(); //唤醒线程}public synchronized void cost()throws InterruptedException{if(list.size()<0){this.wait(); //线程休眠}System.out.println("开始消费,现在数量为:"+list.size());list.remove(0);System.out.println("消费后数量为:"+list.size());this.notify(); //唤醒线程}
}
其次分别时Producer和Cost类,都要继承Thread类,重写run方法
public class Producer extends Thread{ //继承run方法private Market market;public Producer(Market market){this.market=market;}public void run(){while(true) {try {Thread.sleep(new Random().nextInt(500)); //设置时间延迟} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {market.production(); //调用生产方法} catch (InterruptedException e) { // TODO Auto-generated catch blocke.printStackTrace();}}}
public class Cost extends Thread{ //继承run方法private Market market;public Cost(Market market){this.market=market;}public void run(){while(true) {try {Thread.sleep(new Random().nextInt(500)); //设置时间延迟} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {market.cost(); //调用消费方法} catch (InterruptedException e) { // TODO Auto-generated catch blocke.printStackTrace();}}}
最后写出测试类,启动线程
public class Test{public static void main(String[]args){Market market=new Market();Producer p1=new Producer(market);Producer p2=new Producer(market);Producer p3=new Producer(market);Cost c1=new Cost(market);Cost c2=new Cost(market);p1.start(); //启动线程p2.start();p3.start();c1.start();c2.start();}
}
得到的运行结果为:
可知模拟的生产者消费者模式
(三)代码关键点分析:
1.锁问题:
对于Market中的Producer方法和Cost方法,要使用Synchronized关键字同步非静态方法,且要与wait()方法放在一起,使得在多个消费者生产者线程访问Market中的共享资源时不会发生线程安全问题,并且可以保证锁的时同一个对象
public synchronized void producer()public synchronized void cost ()
2.线程的等待与重启
在生产时达到仓库的最大值后,要停止生产,即让生产的线程处于等待状态,此时需要调用wait()方法,
if(list.size()>=20){this.wait(); //线程休眠}
this.notify(); //唤醒线程
要用this来调用wait()方法,而不能用list,是因为被加锁的对象this在调用wait()和notify(),加锁的对象调用 wait() 方法后,线程进入等待状态,直到在加锁的对象上调用 notify() 方法来唤醒之前进入等待的线程
3.While循环放置在Producer和Cost类的run方法中:
使用while循环是原因:要保证线程可以一直运行下去:
public void run(){while(true) {try {Thread.sleep(new Random().nextInt(500)); //设置时间延迟} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {market.cost(); //调用消费方法} catch (InterruptedException e) { // TODO Auto-generated catch blocke.printStackTrace();}}
如果把while循环放在Market中,则睡眠的线程被唤醒之后有可能不满足while()中的条件判定,使得线程线程无法再调用Market中的producer方法,从而无法唤醒线程,因此要放在线程外
4.时间延迟问题:
若要模拟生产和消费的随机过程,还要设置时间延迟
public void run(){while(true) {try {Thread.sleep(new Random().nextInt(500)); //设置时间延迟} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {market.cost(); //调用消费方法} catch (InterruptedException e) { // TODO Auto-generated catch blocke.printStackTrace();}}
放在Producer类中的原因是只有放在run方法中,线程运行时才会具有随机性
否则会发生只有生产达到最大值后才会开始消费
(四)生产者消费者模式相关推荐
- [19/04/11-星期四] 多线程_并发协作(生产者/消费者模式_2种解决方案(管程法和信号灯法))...
一.概念 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型"生产者/消费者模式". Ø 什么是生产者? 生产者指的是负责生产数据的模 ...
- Java中设计模式之生产者消费者模式-3
引言 生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区.其中一个是生产者,用于将消息放入缓冲区:另 ...
- 手撕生产者-消费者模式 | P问题、NP问题
目录 手撕BlockingQueue 生产者-消费者模式 P问题.NP问题 手撕BlockingQueue public class RequestQueue {private final Queue ...
- 并发编程(五)python实现生产者消费者模式多线程爬虫
并发编程专栏系列博客 并发编程(一)python并发编程简介 并发编程(二)怎样选择多线程多进程和多协程 并发编程(三)Python编程慢的罪魁祸首.全局解释器锁GIL 并发编程(四)如何使用多线程, ...
- 生产者/消费者模式的理解及实现
★简介 生产者消费者模式并不是GOF提出的23种设计模式之一,23种设计模式都是建立在面向对象的基础之上的,但其实面向过程的编程中也有很多高效的编程模式,生产者消费者模式便是其中之一,它是我们编程过程 ...
- 【Java】生产者消费者模式的三种实现
原文地址:https://blog.csdn.net/u010983881/article/details/78554671 前言 生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内 ...
- 关于生产者消费者模式的C#实现
今天是圣诞节,大家 Merry Chrismas~ 以前都是在C++项目中写界面,现在接触了C#感觉比MFC和QT好用多了,决定以后除了特殊要求外都用C#开发:).记录一下用C#实现生产者消费者模式吧 ...
- Java多线程(含生产者消费者模式详解)
多线程 导航 多线程 1 线程.进程.多线程概述 2 创建线程 (重点) 2.1 继承Thread类(Thread类也实现了Runnable接口) 2.2 实现Runnable接口(无消息返回) 2. ...
- 【Java】生产者消费者模式的实现
前言 生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据. 阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力.这个 ...
最新文章
- windows 10 代理服务器出现问题
- 第一章 MongoDb概述
- node 升级_技术周刊( Node.js 12 性能大提升 2019-04-30)
- HTML-参考手册: HTTP 方法:GET 对比 POST
- 《Spark核心技术与高级应用》——1.2节Spark的重要扩展
- 【微信小程序】wx:for
- 如果 “ 2X ”的补码是“ 90H ”,那么 X 的真值是( )。
- Request_获取请求体数据
- 论文阅读(2)--Picking Deep Filter Responses for Fine-grained Image Recognition
- sklearn查看数据
- Alec jacobson thesis analysis
- 若依微服务部署遇到问题
- 说出来你可能不信,内核这家伙在内存的使用上给自己开了个小灶!
- 抖音主页头图怎么设置,掌握以下5点技巧即可丨国仁网络资讯
- 什么是APS计划排程系统和生产计划排产系统?
- 禁用计算机的声卡设备,电脑声音被禁用了怎么办
- 计算机二级选择题笔记百度云,计算机二级题库及计算机二级ms office 复习笔记.doc...
- 【1错笔记】psd面试——最长回文子序列 动态规划(2000字超详细解题)
- 百亿富翁 (单调栈)
- 粒子群算法之01背包问题(C语言实现)