在日常开发中我们总是会和网络打交道,从服务端拿数据渲染UI、上传数据到服务器、登陆等,那么就会遇到一些问题。eg:当用户登陆完毕后才获取数据渲染UI或者是多个网络请求从服务端拿到多个数据后,才进行下一步的操作,那么对网络请求之间顺序的控制是十分重要的,本文对这两种情况进行总结,如有不足之处,请多多指教。
情景一:多个网络请求执行(无序)完后,在执行其他操作
#define GlobalQueue dispatch_get_global_queue(0, 0)
#define MainQueue dispatch_get_main_queue()
-
队列组group + notify
- (void)multipleRequest_NoOrder_after_executeOtherTask_byGroupNotify { dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, GlobalQueue, ^{ sleep(1); NSLog(@"网络请求1"); }); dispatch_group_async(group, GlobalQueue, ^{ sleep(1); NSLog(@"网络请求2"); }); dispatch_group_async(group, GlobalQueue, ^{ sleep(1); NSLog(@"网络请求3"); }); dispatch_group_async(group, GlobalQueue, ^{ sleep(1); NSLog(@"网络请求4"); }); //当group中的任务执行完后,会调用 dispatch_group_notify(group, MainQueue, ^{ NSLog(@"更新UI"); }); } 复制代码
-
NSOperation + NSOperationQueue
- (void)multipleRequest_NoOrder_after_executeOtherTask_byOperation { NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"网络请求1"); }]; NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"网络请求2"); }]; NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"网络请求3"); }]; NSBlockOperation *block4 = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"网络请求4"); }]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //设置最大并发数 queue.maxConcurrentOperationCount = [NSProcessInfo processInfo].activeProcessorCount; //waitUntilFinished:是否等待queue中的任务执行完后,才执行后面的代码。会阻塞当前线程 [queue addOperations:@[block1,block2,block3,block4] waitUntilFinished:NO]; //当queue中的所有任务执行完后,会调用 [queue addBarrierBlock:^{ NSLog(@"更新UI"); }]; } 复制代码
-
信号量dispatch_semaphore_t
- (void)multipleRequest_NoOrder_after_executeOtherTask_bySemaphore { //传入的值必须大于等于0 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); dispatch_async(GlobalQueue, ^{ sleep(1); NSLog(@"网络请求1"); dispatch_semaphore_signal(semaphore); }); dispatch_async(GlobalQueue, ^{ sleep(1); NSLog(@"网络请求2"); dispatch_semaphore_signal(semaphore); }); dispatch_async(GlobalQueue, ^{ sleep(1); NSLog(@"网络请求3"); dispatch_semaphore_signal(semaphore); }); dispatch_async(GlobalQueue, ^{ sleep(1); NSLog(@"网络请求4"); dispatch_semaphore_signal(semaphore); }); dispatch_async(MainQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); NSLog(@"更新UI"); }); } 复制代码
-
栅栏函数barrier
- (void)multipleRequest_NoOrder_after_executeOtherTask_byBarrier { dispatch_queue_t queue = dispatch_queue_create("ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ sleep(1); NSLog(@"网络请求1"); }); dispatch_async(queue, ^{ sleep(1); NSLog(@"网络请求2"); }); dispatch_async(queue, ^{ sleep(1); NSLog(@"网络请求3"); }); dispatch_async(queue, ^{ sleep(1); NSLog(@"网络请求4"); }); //坑点:不能用全局并发队列,栅栏函数会失效并且栅栏函数只能用于自定义创建的并发队列,如果传递dispatch_get_global_queue(0, 0),那么dispatch_barrier_async等价于dispatch_async dispatch_barrier_async(queue, ^{ NSLog(@"更新UI"); }); } 复制代码
情景二:多个网络请求执行(有序)完后,在执行其他操作
-
队列组group + enter + leave
- (void)multipleRequest_InOrder_after_executeOtherTask_byGroup { dispatch_group_t group = dispatch_group_create(); dispatch_group_enter(group); [self request:@"1" finished:^{ dispatch_group_leave(group); }]; dispatch_group_enter(group); [self request:@"2" finished:^{ dispatch_group_leave(group); }]; dispatch_group_enter(group); [self request:@"3" finished:^{ dispatch_group_leave(group); }]; dispatch_group_enter(group); [self request:@"4" finished:^{ dispatch_group_leave(group); }]; dispatch_group_notify(group, MainQueue, ^{ NSLog(@"更新UI"); }); } - (void)request:(NSString *)parama finished:(void(^)(void))finished { dispatch_async(GlobalQueue, ^{ NSLog(@"网络请求%@",parama); if(finished) { finished(); } }); } 复制代码
-
信号量
- (void)multipleRequest_InOrder_after_executeOtherTask_bySemaphore { dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); dispatch_async(GlobalQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); sleep(1); NSLog(@"网络请求1"); dispatch_semaphore_signal(semaphore); }); dispatch_async(GlobalQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); sleep(1); NSLog(@"网络请求2"); dispatch_semaphore_signal(semaphore); }); dispatch_async(GlobalQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); sleep(1); NSLog(@"网络请求3"); dispatch_semaphore_signal(semaphore); }); dispatch_async(GlobalQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); sleep(1); NSLog(@"网络请求4"); dispatch_semaphore_signal(semaphore); }); dispatch_async(MainQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); NSLog(@"更新UI"); dispatch_semaphore_signal(semaphore); }); } 复制代码
-
NSOperation + NSOperationQueue(添加任务之间的依赖关系)
- (void)multipleRequest_InOrder_after_executeOtherTask_byOperation { NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"网络请求1"); }]; NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"网络请求2"); }]; NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"网络请求3"); }]; NSBlockOperation *block4 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"网络请求4"); sleep(1); }]; [block4 addDependency:block3]; [block3 addDependency:block2]; [block2 addDependency:block1]; NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; [operationQueue addOperations:@[block1,block2,block3,block4] waitUntilFinished:NO]; //会等到queue中的任务执行完后才会调用 [operationQueue addBarrierBlock:^{ dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"刷新UI"); }); }]; } 复制代码
-
条件NSConditionLock
- (void)multipleRequest_InOrder_after_executeOtherTask_byConditionLock { NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:1]; dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0); /** *lockWhenCondition(加锁):当特定条件值时,才会加锁,否则线程休眠 *unlockWithCondition(解锁):解锁并将条件值设置为传入的值 */ dispatch_async(globalQueue, ^{ [conditionLock lockWhenCondition:1]; NSLog(@"网络请求1"); sleep(1); [conditionLock unlockWithCondition:2]; }); dispatch_async(globalQueue, ^{ [conditionLock lockWhenCondition:2]; NSLog(@"网络请求2"); sleep(1); [conditionLock unlockWithCondition:3]; }); dispatch_async(globalQueue, ^{ [conditionLock lockWhenCondition:3]; NSLog(@"网络请求3"); sleep(1); [conditionLock unlockWithCondition:4]; }); dispatch_async(globalQueue, ^{ [conditionLock lockWhenCondition:4]; NSLog(@"网络请求4"); sleep(1); [conditionLock unlockWithCondition:1]; dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"刷新UI"); }); }); } 复制代码
上面是本人目前掌握的解决方案。如有更好的方式,欢迎大家进行评论交流。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END