博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
信号量dispatch_semaphore的用法
阅读量:6238 次
发布时间:2019-06-22

本文共 2956 字,大约阅读时间需要 9 分钟。

我为什么要用信号量? 因为一个需求。

##需求介绍

这是一个很常见的需求:项目中的业务接口请求的时候需要Token验证。我们最简化这个需求就是:两个请求,请求1成功返回所需参数之后,才能开始请求2。

一个很容易想到的做法就是:

- (void)getToken{    //以上请求的设置忽略    NSURLSessionDataTask *task = [mySession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        if (data) {            NSLog(@"get Token");            //拿到token,传给request请求做参数            [self request:token];        }else{            NSLog(@"token error:%@",error.description);        }     }];    [task resume];}- (void)request:(NSString *)params{    //请求的设置忽略    NSURLSessionDataTask *task = [mySession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        if (data) {            NSLog(@"request success");        }else{            NSLog(@"request error:%@----",error.description);        }    }];    [task resume];}复制代码

这种做法是最容易想到的,但是缺点也是很明显的。获取token的方法与业务层的请求紧密混合在一起了,而且很不容易分离,这会导致你的网络管理类的请求方法变得臃肿。

所以,下面我要用信号量使得token跟业务层的request完成分离开,使代码逻辑更清晰。

##dispatch_semaphore 介绍 dispatch_semaphore只有三个方法:

//创建信号量dispatch_semaphore_create//发送信号量dispatch_semaphore_signal//等待信号量dispatch_semaphore_wait复制代码

执行dispatch_semaphore_create 会根据传入的long型参数创建对应数目的信号量;执行 dispatch_semaphore_signal 会增加一个信号量;执行dispatch_semaphore_wait 则会减少一个信号量,如果信号量是0,就会根据传入的等待时间来等待。

这样一解释,不知道你有没有醍醐灌顶。对于上面的需求,我们在请求token的时候创建信号量为0,成功的话发送信号量,在业务层请求前永久等待信号即可。

看代码:

//请求的按钮点击- (IBAction)buttonPress:(UIButton *)sender{    //创建信号量    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);    [self getToken:semaphore];    //此时的信号量为0,只有token请求成功发送信号量之后,才会往下执行[self request]方法,否则会一直等下去;    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);    [self request];}- (void)getToken:(dispatch_semaphore_t)semaphore{    //以上请求的设置忽略    NSURLSessionDataTask *task = [mySession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        if (data) {            NSLog(@"get Token");           //成功拿到token,发送信号量:            dispatch_semaphore_signal(semaphore);        }else{            NSLog(@"token error:%@",error.description);        }     }];    [task resume];}复制代码

思路理顺了吧~让我们来跑一下程序: 哎呀~卡住了!。。。

是的,因为我们设置了永久等待,所以token请求异步去请求,在当前线程信号量是0,就不会往下执行了,会一直这样卡下去,该怎么解决呢?没错,用异步嘛~

再来代码:

- (IBAction)buttonPress:(UIButton *)sender{    //创建一个并行队列    dispatch_queue_t queque = dispatch_queue_create("GoyakodCreated", DISPATCH_QUEUE_CONCURRENT);    //异步执行    dispatch_async(queque, ^{        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);        [self getToken:semaphore];        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);        [self request];    });        NSLog(@"main thread");}复制代码

再跑一下程序,看控制台打印信息:

如果你还不放心可以多试几次,看看是不是token每次都在request之前。

##总结 我们之所以要这样做,其实只有一个目的就是让代码清晰,这样获取Token的方法可以单独提出一个类,判断token是否过期等逻辑就不会跟业务请求混在一起了,毕竟真正项目运用的时候网络请求类要比demo复杂得多。

##最后

转载地址:http://gezia.baihongyu.com/

你可能感兴趣的文章
Android 程序员学习 iOS ——故事从这里开始
查看>>
【译】Ngnix实现一个缓存和缩略处理的反向代理服务器
查看>>
WebGL实现HTML5贪吃蛇3D游戏
查看>>
webstorm配置eslint注意
查看>>
PHP加密与实际应用
查看>>
ikun 潜入?疑似 B 站后台源码泄露
查看>>
通过 ES6 Promise 和 jQuery Deferred 的异同学习 Promise
查看>>
斯坦福iOS_系列视频之俄罗斯方块
查看>>
JavaScript数据类型的一些注意要点
查看>>
结合P2P软件使用Ansible分发大文件
查看>>
特斯拉Model 3成为核心产品 生产线问题刚好又坏在运输环节 ...
查看>>
如何在Windows系统下的Eclipse中安装Cloud Toolkit
查看>>
阿里云服务器实例规格族配置怎么选?
查看>>
关于K8s集群器日志收集的总结
查看>>
Java中String和StringBuffer对于拼接运算中效率的对比 ...
查看>>
吉利自动驾驶之路将完成:到2022年推出L5级别亚运园区接驳车 ...
查看>>
阿里重磅开源首款自研科学计算引擎Mars,揭秘超大规模科学计算 ...
查看>>
java B2B2C 源码 多级分销Springcloud多租户电子商城系统-使用spring cloud Bus刷新配置...
查看>>
Ionic如何创建自定义展开标题组件
查看>>
用AI简化医疗重复性任务,这家美国创企这样做
查看>>