核心知识点
dispatch_group_t
通过dispatch_group_enter、dispatch_group_leave
成对使用,并通过dispatch_group_notify
监听所有加入到组中的任务完成状态dispatch_semaphore_t
可以通过dispatch_semaphore_wait
来阻塞当前线程、当接收到dispatch_semaphore_signal
信号后继续执行下面代码,以此来控制任务执行的顺序dispatch_semaphore_wait
等待信号量,信号量减1。当信号量< 0时会阻塞当前线程,根据传入的等待时间决定接下来的操作——如果永久等待将等到信号(signal)才执行下去
dispatch_semaphore_signal<br />
释放信号量,信号量加1。当信号量>= 0 会执行wait之后的代码
1. 异步任务请求,结束后返回主线程刷新UI(最常用、最简单)
- (void)dispatch_async_main_queue{
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:3];
NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:mRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求结束线程:%@",[NSThread currentThread]);
// 返回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"回到主线程:%@\n%@",response.URL,[NSThread currentThread]);
});
}];
[dataTask resume];
}
2. 异步 有序/无序 执行组任务,全部执行完毕返回主线程刷新UI
/// 组任务无序异步执行
- (void)group_notify{
NSArray *urls = @[@"https://www.sina.com",@"https://www.baidu.com",@"https://www.jd.com"];
dispatch_group_t dispatchGroup = dispatch_group_create();
for (NSString *urlString in urls) {
NSURLSessionDataTask *dataTask = [self dataTaskWithURLString:urlString completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (error) {
NSLog(@"error:%@",error);
}else{
NSLog(@"任务:%@-%ld\n请求结束线程:%@",response.URL,httpResponse.statusCode,[NSThread currentThread]);
}
dispatch_group_leave(dispatchGroup);
}];
[dataTask resume];
dispatch_group_enter(dispatchGroup);
}
// 设置组任务的超时时常(需要时可以设置)
dispatch_time_t timeout = dispatch_group_wait(dispatchGroup, dispatch_time(DISPATCH_TIME_NOW, 10 *NSEC_PER_SEC));
if (timeout != 0) {
// 可以在此处取消正在进行的组任务
[[NSURLSession sharedSession] getAllTasksWithCompletionHandler:^(NSArray * _Nonnull tasks) {
[tasks enumerateObjectsUsingBlock:^(__kindof NSURLSessionTask * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (obj.state != NSURLSessionTaskStateCompleted) {
[obj cancel];
}
}];
}];
NSLog(@"组任务执行超时_%llu",timeout);
}else{
}
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
NSLog(@"组任务执行完毕,返回主线程进行操作");
});
}
/// 组任务有序异步执行
- (void)group_notify_semaphore{
NSArray *urls = @[@"https://www.sina.com",@"https://www.baidu.com",@"https://www.jd.com"];
dispatch_group_t dispatchGroup = dispatch_group_create();
// 利用信号量来控制请求顺序
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
for (NSString *urlString in urls) {
NSURLSessionDataTask *dataTask = [self dataTaskWithURLString:urlString completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (error) {
NSLog(@"error:%@",error);
}else{
NSLog(@"任务:%@-%ld\n请求结束线程:%@",response.URL,httpResponse.statusCode,[NSThread currentThread]);
}
dispatch_group_leave(dispatchGroup);
// 释放信号量,信号量加1。当信号量>= 0 会执行wait之后的代码
dispatch_semaphore_signal(sem);
}];
[dataTask resume];
dispatch_group_enter(dispatchGroup);
// 等待信号量,信号量减1。当信号量< 0时会阻塞当前线程,根据传入的等待时间决定接下来的操作——如果永久等待将等到信号(signal)才执行下去
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
NSLog(@"组任务执行完毕,返回主线程进行操作");
});
NSLog(@"...");
}
- (NSURLSessionDataTask *)dataTaskWithURLString:(NSString *)urlString completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:3];
NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:mRequest completionHandler:completionHandler];
return dataTask;
}
group_notify
group_notify_semaphore
3. 异步分组执行多段代码
- (void)groups_semaphore{
NSArray *urls1 = @[@"https://www.mi.com",@"https://www.qq.com",@"https://www.sougou.com"];
NSArray *urls2 = @[@"https://www.sina.com",@"https://www.baidu.com",@"https://www.jd.com"];
NSArray *> *groups = @[
urls1,
urls2
];
dispatch_group_t sectionGroup = dispatch_group_create();
// 利用信号量来控制请求顺序
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
for (NSArray *urls in groups) {
dispatch_group_t dispatchGroup = dispatch_group_create();
for (NSString *urlString in urls) {
NSURLSessionDataTask *dataTask = [self dataTaskWithURLString:urlString completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (error) {
NSLog(@"error:%@",error);
}else{
NSLog(@"任务:%@-%ld\n请求结束线程:%@",response.URL,httpResponse.statusCode,[NSThread currentThread]);
}
dispatch_group_leave(dispatchGroup);
}];
[dataTask resume];
dispatch_group_enter(dispatchGroup);
}
dispatch_group_enter(sectionGroup);
// 注意dispatch_queue_t 不能和dispatch_semaphore_wait在同一线程,不然会造成线程死锁
dispatch_group_notify(dispatchGroup, dispatch_get_global_queue(0, 0), ^{
NSLog(@"组任务执行完毕,返回主线程进行操作");
dispatch_group_leave(sectionGroup);
dispatch_semaphore_signal(sem);
});
NSLog(@"...");
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}
dispatch_group_notify(sectionGroup, dispatch_get_main_queue(), ^{
NSLog(@"多组任务都完成了...");
});
}