1.多网络请求未做任何限制性处理(无序完成)
-(void)btnClicked:(UIButton *)psender{
NSURL *url = [NSURL URLWithString:@"https://blog.csdn.net/qq_33226881"];//统一资源定位
NSURLRequest *request = [NSURLRequest requestWithURL:url];//托管请求(层次)实例
NSURLSession *session = [NSURLSession sharedSession];//会话通道(双向/单向)
for (int i=0; i<10; i++) {
//请求过程底层本质(定位数据任务会话通道中实现通信转移)(衍生URLSessionDataTask任务实例)
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {//data规则数据;response响应数据;error异常报错
//completionHandler请求已完成回调块
NSLog(@"---%d",i);
}];
[task resume];//任务开始(触动异步线程)
}
NSLog(@"end");
}
效果:end最先被打印出来,多异步网络请求的回调顺序无序。
2.多网络请求全都无序完成后方可进行某操作
(1)GCD的dispatch_group_t任务组处理
-(void)btnClicked:(UIButton *)psender{
NSURL *url = [NSURL URLWithString:@"https://blog.csdn.net/qq_33226881"];//统一资源定位
NSURLRequest *request = [NSURLRequest requestWithURL:url];//托管请求(层次)实例
NSURLSession *session = [NSURLSession sharedSession];//会话通道(双向/单向)
dispatch_group_t group = dispatch_group_create();//托管任务组(异步线程请求任务)
for (int i=0; i<10; i++) {
dispatch_group_enter(group);
//请求过程底层本质(定位数据任务会话通道中实现通信转移)(衍生URLSessionDataTask任务实例)
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {//data规则数据;response响应数据;error异常报错
//completionHandler请求已完成回调块
NSLog(@"---%d",i);
dispatch_group_leave(group);
}];
[task resume];//任务开始(触动异步线程)
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"end");
});
}
效果:多网络请求全都无序完成后方可进行NSLog(@“end”);打印end
关键4处:
dispatch_group_t group = dispatch_group_create();//托管任务组(异步线程请求任务)(任务组容器)
dispatch_group_enter(group);
dispatch_group_leave(group);
//group必须清空(group任务组容器内存在待执行任务数机制,只有待执行任务数的数目变为0时才会触发信息通知机制)(送入多少个请求任务就必须得有相应的多少个请求任务的离开(也就是说在每个请求任务的completionHandle块域内逻辑位置的最后处必须构建dispatch_group_leave指令(dispatch_group_leave指令放在块域内最外层逻辑位置的最后处(不受成功success失败fail的影响,必须条件判断之外))))
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@“end”);
});
创建托管任务组group实例, 进入dispatch_group_enter任务组group构建数据任务,请求回调完成后通过dispatch_group_leave函数移除数据任务(enter和leave对应配合)。当所有enter的数据任务都leave移除后,任务组group实例会释放发出通知触动执行dispatch_group_notify的block域。
(2)GCD的信号量dispatch_semaphore_t处理(无序)
-(void)btnClicked:(UIButton *)psender{
NSURL *url = [NSURL URLWithString:@"https://blog.csdn.net/qq_33226881"];//统一资源定位
NSURLRequest *request = [NSURLRequest requestWithURL:url];//托管请求(层次)实例
NSURLSession *session = [NSURLSession sharedSession];//会话通道(双向/单向)
dispatch_semaphore_t sem = dispatch_semaphore_create(0);//构建带有发射计数0的信号量(等待必要条件1)
__block int count = 0;//记录所执行的回调块的数目
for (int i=0; i<10; i++) {
//请求过程底层本质(定位数据任务会话通道中实现通信转移)(衍生URLSessionDataTask任务实例)
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {//data规则数据;response响应数据;error异常报错
//completionHandler请求已完成回调块
NSLog(@"---%d",i);
count++;
if (count==10) {//此处说明当前已有10个回调块域执行并完成(对于当前的研究而言即所有异步线程的回调块域都执行完成)即将会触动dispatch_semaphore_signal函数即信号量sem将进行发射(发射计数+1变成1(当发射计数满足大于等于1时触发转换机制变成计数-1返回,所在线程将结束等待从原等待点继续向下运行))
dispatch_semaphore_signal(sem);//发射管理信号量sem
count = 0;
}
}];
[task resume];//任务开始(触动异步线程)
}
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);//必要条件2:触动dispatch_semaphore_wait函数(此时信号量携带0)进入所在线程等待状态(等待时间持续FOREVER永久)即此时所在线程下面的NSLog(@"end");指令不会被触动
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"end");
});
}
效果:多网络请求全都无序完成后方可进行NSLog(@“end”);打印end
关键处3处:
dispatch_semaphore_t sem = dispatch_semaphore_create(0);//构建带有发射计数0的信号量(等待必要条件1)
dispatch_semaphore_signal(sem);//发射管理信号量sem
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);//必要条件2:触动dispatch_semaphore_wait函数(此时信号量携带0)进入所在线程等待状态(等待时间持续FOREVER永久)即此时所在线程下面的NSLog(@“end”);指令不会被触动
3.多网络请求全都有序完成后方可进行某操作
(1)GCD的信号量dispatch_semaphore_t处理(有序)
-(void)btnClicked:(UIButton *)psender{
NSURL *url = [NSURL URLWithString:@"https://blog.csdn.net/qq_33226881"];//统一资源定位
NSURLRequest *request = [NSURLRequest requestWithURL:url];//托管请求(层次)实例
NSURLSession *session = [NSURLSession sharedSession];//会话通道(双向/单向)
dispatch_semaphore_t sem = dispatch_semaphore_create(0);//构建带有发射计数0的信号量(等待必要条件1)
for (int i=0; i<10; i++) {
//请求过程底层本质(定位数据任务会话通道中实现通信转移)(衍生URLSessionDataTask任务实例)
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {//data规则数据;response响应数据;error异常报错
//completionHandler请求已完成回调块
NSLog(@"---%d",i);
dispatch_semaphore_signal(sem);//发射管理信号量sem(发射计数+1变成1(当发射计数满足大于等于1时触发转换机制变成计数-1返回,所在线程将结束等待从原等待点继续向下运行))
}];
[task resume];//任务开始(触动异步线程)
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);//必要条件2:触动dispatch_semaphore_wait函数(此时信号量携带0)进入所在线程等待状态(等待时间持续FOREVER永久)即此时所在线程下面的NSLog(@"end");指令不会被触动
}
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"end");
});
}
效果:多网络请求全都有序完成后方可进行某操作
通过GCD的信号量dispatch_semaphore_t处理实现多网络请求全都有序完成后方可进行某操作,明显感觉出整个全都有序完成过程需要花费的时间大大增加,不像在无序中同时(几乎)开启任务以等待完成回调,此处有序下是一个数据任务请求发出,等待,回调完成后发出第二个数据任务请求,等待,完成后再发出第三个数据任务,这样等待的总时间是多个数据任务请求每一个回调时间的总和,在时间上大大增加了消耗且dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER)函数是会阻塞线程的,可能导致界面卡顿。(不推荐)
(2)采用NSConditionLock条件锁实现多网络请求全都有序完成(重点推荐)
-(void)btnClicked:(UIButton *)psender{
NSURL *url = [NSURL URLWithString:@"https://blog.csdn.net/qq_33226881"];//统一资源定位
NSURLRequest *request = [NSURLRequest requestWithURL:url];//托管请求(层次)实例
NSURLSession *session = [NSURLSession sharedSession];//会话通道(双向/单向)
NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:0];//构建ConditionLock条件锁对象实例托管,锁条件为0
dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);//开辟队列
for (int i=0; i<10; i++) {
//请求过程底层本质(定位数据任务会话通道中实现通信转移)(衍生URLSessionDataTask任务实例)
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {//data规则数据;response响应数据;error异常报错
//completionHandler请求已完成回调块
dispatch_async(queue, ^{
[lock lockWhenCondition:i];//当锁条件满足i时 加锁
NSLog(@"---%d",i);
[lock unlockWithCondition:i+1];//解锁,并重置锁的条件为i+1
});
}];
[task resume];//任务开始(触动异步线程)
}
}
效果:多网络请求全都有序完成
关键3处:
NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:0];//构建ConditionLock条件锁对象实例托管,锁条件为0
dispatch_queue_t queue = dispatch_queue_create(“concurrentQueue”, DISPATCH_QUEUE_CONCURRENT);//开辟队列
[lock lockWhenCondition:i];//当锁条件满足i时 加锁
[lock unlockWithCondition:i+1];//解锁,并重置锁的条件为i+1
添加代码理解:
1、初始化了一个锁,并添加锁条件为0
2、当i满足锁条件的时候就进行加锁
3、进行解锁,并重置锁的条件为i+1