美文网首页
信号量dispatch_semaphore_t创建网络同步请求

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

作者: rainbowboy | 来源:发表于2018-08-14 16:16 被阅读43次

当我需要查询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后面的代码。

相关文章

网友评论

      本文标题:信号量dispatch_semaphore_t创建网络同步请求

      本文链接:https://www.haomeiwen.com/subject/zcdvbftx.html