信号量的使用场景
开发中经常会遇到如下两种业务场景:
1 某一个界面需要同时发多个请求,全部请求都成功后再一起刷新界面
2 多个请求必须按照一定顺序执行
3 控制线程开启的数量
这时信号量的作用就显得很牛逼了
信号量常用的三个方法如下所示:
- dispatch_semaphore_create:创建一个信号量(semaphore)
- dispatch_semaphore_signal:信号通知,即让信号量+1
- dispatch_semaphore_wait:等待,直到信号量大于0时,即可操作,同时将信号量-1
问题1解决方案:
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //请求1
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[网络请求:{
成功:dispatch_semaphore_signal(sema);
失败:dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //请求2
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[网络请求:{
成功:dispatch_semaphore_signal(sema);
失败:dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //请求3
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[网络请求:{
成功:dispatch_semaphore_signal(sema);
失败:dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ //界面刷新 NSLog(@"任务均完成,刷新界面"); });
问题2解决方案
//第一步:获取token
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
[self task_1];
}];
//第二步:上传七牛
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
[self task_2];
}];
//第三步:图片地址上传服务器
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
[self task_3];
}];
//设置依赖
[operation2 addDependency:operation1]; //任务二依赖任务一
[operation3 addDependency:operation2]; //任务三依赖任务二
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];
- (void)task_1
{
//创建信号量并设置计数默认为0
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self.entityRequest postGetQiNiuTokenSuccess:^(NS_M_RequestOutput *json) {
//请求成功 计数+1操作
dispatch_semaphore_signal(sema);
} failure:^(NSString *msg) {
//请求失败 计数+1操作
dispatch_semaphore_signal(sema);
} error:^(NSError *error) {
//请求异常 计数+1操作
dispatch_semaphore_signal(sema);
}];
//若计数为0则一直等待
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
- (void)task_2
{
//创建信号量并设置计数默认为0
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self.entityRequest postGetQiNiuTokenSuccess:^(NS_M_RequestOutput *json) {
//请求成功 计数+1操作
dispatch_semaphore_signal(sema);
} failure:^(NSString *msg) {
//请求失败 计数+1操作
dispatch_semaphore_signal(sema);
} error:^(NSError *error) {
//请求异常 计数+1操作
dispatch_semaphore_signal(sema);
}];
//若计数为0则一直等待
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
- (void)task_3
{
//创建信号量并设置计数默认为0
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self.entityRequest postGetQiNiuTokenSuccess:^(NS_M_RequestOutput *json) {
//请求成功 计数+1操作
dispatch_semaphore_signal(sema);
} failure:^(NSString *msg) {
//请求失败 计数+1操作
dispatch_semaphore_signal(sema);
} error:^(NSError *error) {
//请求异常 计数+1操作
dispatch_semaphore_signal(sema);
}];
//若计数为0则一直等待
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
问题3解决方案(控制允许同时并发的操作最多只有5次)
dispatch_semaphore_t sema = dispatch_semaphore_create(5); for (100次循环操作) { dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 操作 dispatch_semaphore_signal(sema); }); }