信号量dispatch_semaphore_t创建网络同步请求

当我需要查询3000条大盘股票数据并进行分析的时候,需要一条一条的检索数据,不能乱了,3000条并发请求会导致手机网络卡死中断,所以想能有某个机制实现网络同步请求,这样我就能一条一条的获取数据并分析了。
于是我找到了信号量:dispatch_semaphore_t

1、 dispatch_semaphore有三个方法:

//创建信号量
dispatch_semaphore_create
//释放信号量
dispatch_semaphore_signal
//等待信号量
dispatch_semaphore_wait

2、用法

//创建:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); //创建信号量。括号里的参数表示当前可以同步执行几条数据。

//释放信号量
dispatch_semaphore_signal(semaphore);

//等待信号量
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

3、解释

dispatch_semaphore_create(0);//创建信号量并且可以同步执行0条数据。
dispatch_semaphore_signal(semaphore);//会使信号量加1,执行之后就可以同步执行1条数据了。
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
/*会使信号量减1。当semaphore的值不大于0时,信号量减1,同时后续代码
会继续执行,但是当semaphore的值等于0时,信号量不做减1动作,同时
阻塞当前的执行,在timeout之前遇到semaphore大于0时,会继续做减1操
作,并执行后续代码。*/

4、范例

- (void)calcuteAll {
    
    NSInteger sourceArrCount = self.sourceArr.count;
    
    __weak typeof(&*self) weakSelf = self;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); //创建信号量
        weakSelf.clearCalcuteAllArr = YES;
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf.activeView startAnimating];
        });
        
        for (NSInteger i = 0; i < sourceArrCount; i++) {
            NSDictionary *dataDic = weakSelf.sourceArr[i];
            NSString *stockCode = dataDic[code];
            weakSelf.currentCode = stockCode;
            weakSelf.currentName = dataDic[name];
            
            NSString *headFixStr = @"sh";
            
            NSString *headStr = [stockCode substringToIndex:2];
            if ([headStr isEqualToString:@"60"]) {
                headFixStr = @"sh";
            }else if ([headStr isEqualToString:@"00"]) {
                headFixStr = @"sz";
            }else if ([headStr isEqualToString:@"30"]) {
                headFixStr = @"sz";
            }else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    kViewMessageView(@"不是沪深A股也不是创业板")
                });
                return;
            }
            
            NSString *stockCodeWithHeadStr = [headFixStr stringByAppendingString:stockCode];
            
            NSString *stockSourceUrl = [NSString stringWithFormat:@"**/?symbol=%@&scale=240&ma=no&datalen=%ld",stockCodeWithHeadStr,(long)weakSelf.dayLength];
            
           [weakSelf.sessionManager POST:stockSourceUrl parameters:@{} progress:^(NSProgress * _Nonnull uploadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                NSString *dataStr = [[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding];
                
                [weakSelf calcuteAllWithDataStr:dataStr];
                
               dispatch_semaphore_signal(semaphore);//释放信号量,使其加1
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                dispatch_semaphore_signal(semaphore);//释放信号量,使其加1
                
            }];
            
            dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//当信号量的值为0时阻塞当前执行,直到值大于0时做减1操作,并执行后续代码
            weakSelf.clearCalcuteAllArr = NO;
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf.activeView stopAnimating];
            [weakSelf saveCalcuteResult];
        });
        
    });

    
}
/*我这个self.sourceArr里有3千个股票代码,请求这3千个股票的数据,
肯定会导致网络阻塞的。所以想着一条一条的请求,遍历完成之后处理
自己需要的数据*/

5、注意点
信号量的使用不要在主线程中,否则会阻塞主线程。需要在非主线程里异步执行。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//请在这里处理信号量
});

6、返回值说明

//释放信号量
long dispatch_semaphore_signal(semaphore);
/*当返回值为0时表示当前并没有线程等待其处理的信号量,其处理
的信号量的值加1即可。当返回值不为0时,表示其当前有(一个或多个)
线程等待其处理的信号量,并且该函数唤醒了一个等待的线程
(当线程有优先级时,唤醒优先级最高的线程;否则随机唤醒)。*/
//等待信号量
long dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

/*
当其返回0时表示在timeout之前,该函数所处的线程被成功唤醒。
当其返回不为0时,表示timeout发生。
*/

7、对信号量的比喻

大家都见过女生排队上厕所的场景吧,特别是在知名景点,很壮观。公共女厕只有5个厕位,顶多进去5个。当dispatch_semaphore_wait发现信号量的值是0时,剩下的就得排队等着;当一女生如厕完成出来,就会调用dispatch_semaphore_signal告知下一个排队的女生可以如厕了,此时就会执行dispatch_semaphore_wait后面的代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法。这大概是史上最详细、清晰的关于 GCD 的详细讲...
    花花世界的孤独行者阅读 3,434评论 0 1
  • 1.GCD信号量简介 GCD信号量机制主要涉及到以下三个函数: dispatch_semaphore_create...
    VV木公子阅读 41,223评论 18 230
  • 我说不知道一个人跑到这么远的地方是为了什么。 他说难道你从来没有问过自己这个问题吗? 我愣了一下。 是...
    洛家仁人阅读 2,635评论 0 0
  • 现在的朋友聚餐,餐前打牌是为了等人。而同好者往往会特意提前,只是为了有在一起打牌的机会,而酒足饭饱后的打牌,就是真...
    大麦茶的故事阅读 1,423评论 0 0
  • 那是我最爱的玫瑰,我想念她! 小王子从那颗不知名的星球来到地球,遇见了很多不一样的人,他想过要和狐狸在一起,于是他...
    园丁备忘录阅读 5,051评论 0 1