iOS如何判断多个异步线程是否执行完毕
2017-07-05 本文已影响1475人
风与鸾
前言
在实际开发中有A、B、C、D异步请求,需要A、B、C、D执行完,然后去执行其他线程。有什么办法可以处理?
方法一:RunLoop
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"A");
CFRunLoopStop(CFRunLoopGetMain());
}] ;
[task resume];
CFRunLoopRun();
NSLog(@"B");
这里执行结果是先输出A后在输出B,注意CFRunLoopRun()的位置
方法二:GCD的group
- 原理就是利用
dispatch_group_async
执行完queue
会执行dispatch_group_notify
回调 - 多线程操作时这个方法使用频繁
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{
NSLog(@"A");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"B");
});
输出A后再输出B
方法三:dispatch_barrier_async
- 一般使用dispatch_barrier_async, 会让barrier之前的线程执行完成之后才会执行barrier后面的操作,起到一个阻挡的作用。
dispatch_queue_t queue = dispatch_queue_create(0, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"A");
});
dispatch_async(queue, ^{
NSLog(@"C");
});
dispatch_barrier_async(queue, ^{
NSLog(@"拿到了A的值");
});
dispatch_async(queue, ^{
NSLog(@"D");
});
dispatch_async(queue, ^{
NSLog(@"E");
});dispatch_async(queue, ^{
NSLog(@"F");
});
A、C输出顺序不固定,然后输出拿到了A的值,然后D、E、F输出顺序不固定
这里指定的并发队列是自己通过dispatch_queue_create函数创建的,如果你传的是一个串行队列或者全局并发队列,这个函数等同于dispatch_async函数
方法四:NSOperationQueue
- 主要就是用到NSOperationQueue的一个对象方法
addDependency :
- 需要注意一点:
waitUntilFinished
如果是YES,必须等到queue中所有Operation执行完毕之后, 才会打D, 起到一个阻塞的作用,反之的话, D的打印顺序是随机的了,就看哪个线程跑得快了...
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *p1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"A");
}];
NSBlockOperation *p2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"B");
}];
NSBlockOperation *p3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"C");
}];
[p3 addDependency:p1];
[p1 addDependency:p2];
// waitUntilFinished是否阻塞当前线程
[queue addOperations:@[p1,p2,p3] waitUntilFinished:YES];
// 如果是NO,那么这行打印就是随机的, 反之就是等A,B,C都打印完之后才执行
NSLog(@"D");
输出C、A、B再输出D
结束
- 相信很多的初学iOS开发人员对于这种场景习惯在
success
回调中再嵌套一个异步线程,嵌套固然可以达到效果,但是代码的可读性就变差了。 - 相信你看到文章结尾你已经
get
到新tip
了。 - 实现的方式还有很多,如果你想到了欢迎留言。