IOS多线程使用GCD与信号量实现生产者与消费者模式
一、原理的简述
在生产者消费者模式当中,首先需要分清在这个模式当中有哪些角色?
各角色分别担任什么职责与它们之间的关系如何?
角色之间是在保证数据的准确性的情况下如何通信(同步数据)的?
假设现在有一个这样的情形:
有两个人共同访问一个容量有限的仓库,这2个人,其中一个是生产鞋子的,另一个是售卖鞋子,
他们共同使用一个仓库。在使用这个仓库之前,这2人之间需要建立一种规约,即:
1.生产鞋子的人首先需要向仓库管理员申请钥匙,在拿到钥匙的时候需要判断两种情况
在满仓的时候不能再让生产鞋子的人继续往这个仓库中存放鞋子,因为这个仓库的容量有限,
继续放会出现爆仓,那么这个时候生产鞋子的人应该怎么做呢?很明显,让它把仓库钥匙交出来,
然后出去等待。当仓库出现有位置空的时候,才继续存放鞋子。
2.卖鞋子的时候在使用这个仓库之前也需要向仓库管理员申请钥匙,当仓库有鞋子的时候,
把鞋子拿出来去卖,否则归还钥匙出仓等待。
3.这个仓库只有一把钥匙,即同时只能限制一个人进来。
二、将问题程序化:
.h文件:
//
// BaseRoom.h
// MultiThread
//
// Created by liuxiaobing on 2018/10/31.
// Copyright © 2018 liuxiaobing. All rights reserved.
//#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN/**仓库*/
@interface BaseRoom : NSObject@property(strong,nonatomic) NSMutableArray* list;@property(assign,nonatomic) BOOL bIsStop;@property(strong,nonatomic) NSMutableArray* baseList; //仓库
@property(strong,nonatomic) dispatch_semaphore_t mutex; //访问仓库(临界区)的互斥访问信号量
@property(strong,nonatomic) dispatch_semaphore_t comsumer_sem; //生产者-是否生产对象的标记 消费者是否消费仓库对象的标记 使用信
@property(strong,nonatomic) dispatch_semaphore_t product_sem; //生产者-是否生产对象的标记 消费者是否消费仓库对象的标记 使用信
@property(nonatomic,assign) int count;-(void) produce:(NSString*) e;-(NSString*) comsumer;@endNS_ASSUME_NONNULL_END
.m文件 :
//
// BaseRoom.m
// MultiThread
//
// Created by liuxiaobing on 2018/10/31.
// Copyright © 2018 liuxiaobing. All rights reserved.
//#import "BaseRoom.h"@implementation BaseRoom- (instancetype)init
{self = [super init];if (self) {//新建一个仓库,这里暂不作容量设计self.baseList = [[NSMutableArray alloc] init];//初始化生产对象--消费者标记,初始为0表示什么都没有self.product_sem = dispatch_semaphore_create(10);self.comsumer_sem = dispatch_semaphore_create(0);//初始化临界区互斥访问信号量,用信号量实现互斥,特殊初始值为1.//控制同一时刻只有一个线程对象在访问仓库self.mutex = dispatch_semaphore_create(1);}return self;
}-(void)produce:(NSString *)e{long baseCount = dispatch_semaphore_wait(self.mutex, 5 * NSEC_PER_SEC); //先获取访问仓库的信号量if(baseCount != 0){NSLog(@"39----------仓库有人正在使用,生产者处于等待");}long maxSpaceCount = dispatch_semaphore_wait(self.product_sem, 5 * NSEC_PER_SEC); //再判断 仓库是否还有可放物品的空间if(maxSpaceCount != 0){NSLog(@"43----------仓库10个空间已经使用完,生产者处于等待:仓库容量:%lu",[self.baseList count]);}else{[self.baseList addObject:e];NSLog(@"40---------生产鞋子%@:w仓库目前有:%lu",e,[self.baseList count]);dispatch_semaphore_signal(self.mutex); //生产完了释放临界区的访问锁dispatch_semaphore_signal(self.comsumer_sem); //将仓库中的皮鞋数量加1}}-(NSString*) comsumer{NSString* e = nil;long baseCount = dispatch_semaphore_wait(self.mutex, 5 * NSEC_PER_SEC); //先获取访问仓库的信号量if(baseCount != 0){NSLog(@"55----------仓库有人正在使用,消费者处于等待");}long avableCount = dispatch_semaphore_wait(self.comsumer_sem, 5 * NSEC_PER_SEC); //再判断 仓库是否还有可取,如果有物品,则取一个出来,否则t等待if(avableCount != 0){NSLog(@"59----------空仓,消费者处于等待");}else{e = [self.baseList objectAtIndex:[self.baseList count] -1];[self.baseList removeLastObject];NSLog(@"50---------卖鞋子:%@ 仓库还有%lu:",e,[self.baseList count]);dispatch_semaphore_signal(self.mutex); //生产完了释放临界区的访问锁dispatch_semaphore_signal(self.product_sem); //将仓库中的可放置的数量 +1}return e;
}@end
测试页面:
.h文件
//
// ProComsumerModel.h
// MultiThread
//
// Created by liuxiaobing on 2018/10/31.
// Copyright © 2018 liuxiaobing. All rights reserved.
//#import <UIKit/UIKit.h>
#import "BaseRoom.h"NS_ASSUME_NONNULL_BEGIN/**生产者消费者模式*/
@interface ProComsumerModel : UIViewController@property(nonatomic,strong) BaseRoom* baseroom;//生产者线程跑的队列,这个队列可以控制生产者的执行是并行还是串行
@property(strong,nonatomic)dispatch_queue_t producerQueue;//消费者线程跑的队列,这个队列可以控制消费者的执行是并行还是串行
@property(strong,nonatomic) dispatch_queue_t consumerQueue;-(void) initObj;@endNS_ASSUME_NONNULL_END
.m
//
// ProComsumerModel.m
// MultiThread
//
// Created by liuxiaobing on 2018/10/31.
// Copyright © 2018 liuxiaobing. All rights reserved.
//#import "ProComsumerModel.h"
#import "ProComsumerModel.h"@interface ProComsumerModel ()@end@implementation ProComsumerModel- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor whiteColor];[self initObj];[self initView];}-(void) initView{UIButton* button2 = [UIButton buttonWithType:UIButtonTypeCustom];[button2 setTitle:@"生产" forState:UIControlStateNormal];button2.frame = CGRectMake(20, 80, 200, 40);button2.backgroundColor = [UIColor brownColor];[button2 addTarget:self action:@selector(producer:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:button2];UIButton* button3 = [UIButton buttonWithType:UIButtonTypeCustom];[button3 setTitle:@"消费" forState:UIControlStateNormal];button3.frame = CGRectMake(20, 180, 200, 40);button3.backgroundColor = [UIColor brownColor];[button3 addTarget:self action:@selector(comsumer:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:button3];
}-(void)producer:(UIButton*) button{[self producter];
}-(void)comsumer:(UIButton*) button{[self comsumer];
}-(void) initObj{self.baseroom = [[BaseRoom alloc] init];//分别创建N个生产者和M消费者各自的运行并发队列//均使用并发队列,即生产者之间可以并发执行,消费者之间也可以并发执行self.producerQueue = dispatch_queue_create("producer", DISPATCH_QUEUE_CONCURRENT);self.consumerQueue = dispatch_queue_create("consumer", DISPATCH_QUEUE_CONCURRENT);}-(void) producter{// //创建10个生产者持续生产皮鞋
// for (int i = 0; i < 1; i++) {
//
// }dispatch_async(self.producerQueue, ^{while(1){NSString* t = [NSString stringWithFormat:@"nike"];[self.baseroom produce:t];sleep(1);}});}-(void)comsumer{dispatch_async(self.consumerQueue, ^{while(1){[self.baseroom comsumer];sleep(2);}});}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end
测试效果:
工程源码
IOS多线程使用GCD与信号量实现生产者与消费者模式相关推荐
- iOS 多线程和GCD(Grand Central Dispath) 教程 (一)
iOS 多线程和GCD(Grand Central Dispath) 教程 (一) 本文翻译自 Ray Wenderlich 的博客 点击打开原文链接.全部由本人亲手翻译...童叟无欺~ 你有木有遇 ...
- 多线程通信—生产者和消费者模式
1.队列Queue: 从一个线程向另一个线程发送数据最安全的方式可能就是使用queue库中的队列了.创建一个被多个线程共享的Queue对象,这些线程通过使用put()和get()操作来向队列中添加或者 ...
- python 多线程并发编程(生产者、消费者模式),边读图像,边处理图像,处理完后保存图像实现提高处理效率
文章目录 需求 实现 先导入本次需要用到的包 一些辅助函数 如下函数是得到指定后缀的文件 如下的函数一个是读图像,一个是把RGB转成BGR 下面是主要的几个处理函数 在上面几个函数构建对应的处理函数 ...
- Java并发编程系列18:多线程之生产者和消费者模式_信号灯法(wait/notify通知机制)
1.生产者消费者模式 生产者消费者问题(Producer-consumer problem),也称为有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题 ...
- Java基础进阶多线程-生产者和消费者模式
1.什么是"生产者和消费者模式"? 生产线程负责生产,消费线程负责消费 生产线程和消费线程要达到均衡 这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和notify方 ...
- 设计模式-生产者与消费者模式
最近正在看C++日志的开源代码,其中多个线程需要向文件中写入日志信息,该将该算法逻辑抽象出来的话就是生产者与消费者设计模式.常见的生产者与消费者模式主要分为四类:单生产者与单消费者模式.单生产者与多消 ...
- Python中的生产者与消费者模式(转载)
利用多线程和队列可以实现生产者消费者模式.该模式通过平衡生产线程和消费线程的工作能力来提高程序整体处理数据的速度. 1.什么是生产者和消费者? 在线程世界里,生产者就是生产数据(或者说发布任务)的线程 ...
- Java多线模式-Producer-Consumer模式(生产者、消费者模式)
1.场景 有些时候需要两个或两个以上的线程协同工作,每个线程需要使用其他线程产生数据. 2.详细说明 可以把上面的场景抽象成生产者和消费者模式.从消费者的角度:消费者需要消费生产者生成的产品. 从生产 ...
- python 生产者和消费者模式_Python爬虫:生产者和消费者模式
认识生产者和消费者模式 生产者和消费者是多线程中很常见的一个问题.产生数据的模块,我们称之为生产者,而处理数据的模块,就称为消费者.但是单单只有生产者和消费者显然还是不够的,一般来说,我们还有一个缓冲 ...
最新文章
- UNITY 多个子MESH与贴图的对应关系
- 连接数据库版本不一致
- CortexM0开发 —— LPC11C14的UART使用方法
- java验证码的代码_java实用验证码的实现代码
- java集群_「Java知识」MyCat的图文视频讲解,MyCat分片集群分表分库策略
- 计算机无法进系统咋办,详解电脑无法进入系统怎么办
- JSP 新手入门理解教程(附带案例)
- 画法几何与工程制图2
- 计算机技术领域当前的主流技术及其社会需求调查报告
- samtools faidx输出的fai文件格式解析 | fasta转bed | fasta to bed
- 台积电工厂突发停电:或损失2亿元
- Day 15 正则表达式
- 计算机游戏开发职业生涯规划,计算机动漫设计与制作专业职业生涯规划书
- python实现-用随机森林填补缺失值、均值填充0填充的比较
- js加密大全(防止客户端查看自己的js文件)
- JFrame添加图片以及使用的教程
- 在Java中将excel文件转换成pdf文件
- python 爬取贝壳的一些思路和方法设计(用地址找到小区名字)
- Nessus漏洞扫描教程之安装Nessus工具
- Java BufferedInputStream available()方法与示例
热门文章
- 亚马逊开店创业 稳扎稳打稳赚钱
- arcgis server 学习(一) 地图要素查询
- asp 打开服务器文件夹,什么是ASP?如何打开ASP文件
- 用html写个人简历(学生学习所用)
- 香港室内设计公司【Junee】申请纳斯达克IPO上市,募资2500 万美元
- [sensorhub]MT6752/32平台sensor hub KK和L版本配置方法
- 工作日记:CSS 让img变成颜色变成白色/黑色
- 天弘基金移动App客户端架构优化之路
- 脚印(Foot Print)效果制作
- 聊聊C++任务定时器的设计与具体实现