前言
总感觉这个标题怪怪的,但是我自身词汇有限,也不知道怎么描述好了.用一个简单的需求来解释一下吧.我之前开发的一个项目,需要向服务器上传图片,多图片上传,然后每次上传之后会返回一个图片的AID, 然后需要所有图片上传完成之后, 拿着一个全是AID的数组作为参数进行另一个异步请求...好吧,我感觉又绕了...
前几天,我在一个技术交流圈,看到一个朋友去
JINGDONG
的面试题, 其中一个题目的描述是:有a、b、c、d 4个异步请求,如何判断a、b、c、d都完成执行?
, 跟我上面的需求大同小异.所以在这儿,我把我工作中曾经用到过的一些方法做一个小的总结,有遗漏的或者错误的地方,请大家留意指正,非常感谢哈!!!
特别注意:所有的代码都基于JINGDONG这道面试题, 不过我只打印了A和B而已..
小结
1. RunLoop
- 需要注意一点: 这儿用的是
NSURLSession
, 不是AFN
, 所以block里面的线程是子线程,不是主线程, 不能直接使用CFRunLoopGetCurrent
- CFRunLoopGetCurrent : Returns the CFRunLoop object for the current thread.
- CFRunLoopGetMain: Returns the main CFRunLoop object.
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");
2. GCD的group
- dispatch_group_notify就是需要等queue里面的子线程都执行完毕之后才会执行
- 这种方法比较常见, 不多说
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");
});
3. dispatch_barrier_async
- barrier的中文意思就是障碍, 屏障
- 一般使用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");
});
4.NSOperationQueue
- 主要就是用到NSOperationQueue的一个对象方法
-addDependency
- 需要注意一点:
waitUntilFinished
如果是YES
,必须等到queue
中所有Operation
执行完毕之后, 才会打印HAHA
, 反之的话,HAHA
的打印顺序是随机的了,就看哪个线程跑得快了...
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];
[p3 addDependency:p2];
// waitUntilFinished是否阻塞当前线程
[queue addOperations:@[p1,p2,p3] waitUntilFinished:NO];
// 如果是NO,那么这行打印就是随机的, 反之就是等A,B,C都打印完之后才执行
NSLog(@"HAHA");
5. 使用AFN
中的batchOfRequestOperations
- 这个和GCD一样, 我工作中比较常用的一种方法
-
batchOfRequestOperations
方法其实是AFHTTPRequestOperation的父类AFURLConnectionOperation
的一个方法. - 这儿的
waitUntilFinished
同4. NSOperationQueue
-
progressBlock
一般用在进度计算中, 比如执行了多少百分比, 可以自定义一些炫酷动画
AFHTTPRequestOperation *queue = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
[queue setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"A");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"A");
}];
[queue resume];
AFHTTPRequestOperation *queue2 = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
[queue2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"B");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"B");
}];
[queue2 resume];
NSArray *operations = [AFHTTPRequestOperation batchOfRequestOperations:@[queue, queue2] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
NSLog(@"%ld/%ld", numberOfFinishedOperations, totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
NSLog(@"C");
}];
[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];
6.其他
- 老早以前, 我一般是在一个异步请求中的
completionBlock
或者successBlock
中拿到需要的值, 为空判断后,直接在block里面再写一个异步线程...其实这样的写法可能很多人都用过,但是代码的阅读性太弱了,花括号太多,看的眼花缭乱的... - 其实还可以设置flag进行判断等等方法...
- 暂时就想到这么多, 还有别的方案的话, 欢迎留言哈,大家共同学习!!!
联系我
<a href="https://github.com/SunLiner">github</a>
<a href="http://www.weibo.com/5589163526/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1">微博</a>
<a href="//www.greatytc.com/users/9723687edfb5/latest_articles">简书</a>