多网络请求全都执行完成方可执行某操作

在这里插入图片描述
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HaiJunYa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值