開發中經常會遇到如下兩種業務場景:
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); }); }
