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