等待多個異步操作
例如有這樣一個場景,有三個異步操作A,B,C, A與B相互不依賴,但是操作C需要等A和B都執行結束後才能執行
方法一: dispatch_group
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("a", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
NSLog(@"block A start");
sleep(5);
NSLog(@"block A end");
});
dispatch_group_async(group, queue2, ^{
NSLog(@"block B start");
sleep(10);
NSLog(@"block B end");
});
dispatch_group_notify(group, queue3, ^{
NSLog(@"block C start");
});
原理:dispatch_group可以監測多個block對象,記錄當前group中有多少個block對象在執行,並在當前group中的所有block對象都執行完之後執行一個特定的block。具體方法為 dispatch_group_async方法可以將block加入到指定的dispatch_group中(可以理解為數量上+1),當block執行結束時再將其移除,而dispatch_group_notify方法會在指定的group中所有的block都執行完之後再去執行相應的block
方法二: dispatch_barrier_async
dispatch_async(queue, ^{
NSLog(@"block A start");
sleep(5);
NSLog(@"block A end");
});
dispatch_async(queue, ^{
NSLog(@"block B start");
sleep(10);
NSLog(@"block B end");
});
dispatch_barrier_async(queue, ^{
NSLog(@"block C start");
});
原理:通過dispatch_barrier_async添加的block會在當前異步隊列中在它之前添加的其他的block都執行完畢後才執行自己的block,在dispatch_barrier_async之後添加的block會等通過dispatch_barrier_async添加的block執行完畢之後才會執行
方法三:NSOperationQueue
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block A start");
sleep(5);
NSLog(@"block A end");
}];
NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block B start");
sleep(10);
NSLog(@"block B end");
}];
NSOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block C start");
}];
[operation3 addDependency:operation1];
[operation3 addDependency:operation2];
[operationQueue addOperation:operation1];
[operationQueue addOperation:operation2];
[operationQueue addOperation:operation3];
原理:NSOperationQueue支持添加dependency
方法四:dispatch_group_enter dispatch_group_leave
以上三種方法適用場景為我們能夠控制異步返回block的情況,當我們對異步返回的block沒有控制權時,比如有回調block的方法,上述方法就失效了,此時就需要用到 dispatch_group_enter dispatch_group_leave
比如有一個方法
- (void)handleSomethingForSeconds:(NSInteger)seconds withCompletion:(void (^)())completion
我們對completion沒有直接控制權此時需要如下處理
dispatch_group_t group2 = dispatch_group_create();
dispatch_group_enter(group2);
[self handleSomethingForSeconds:5 withCompletion:^{
NSLog(@"complete A");
dispatch_group_leave(group2);
}];
dispatch_group_enter(group2);
[self handleSomethingForSeconds:10 withCompletion:^{
NSLog(@"complete B");
dispatch_group_leave(group2);
}];
dispatch_group_notify(group2, queue, ^{
NSLog(@"block C start");
});
原理:dispatch_group_enter會顯示地給指定group中記錄的正在執行的block數加一,dispatch_group_leave會顯示地給指定group中記錄的正在執行的block數減一,其他原理跟方法一相同,以此來實現等待的目的。
等待多個異步操作