iOS基础

iOS 异步并发多个网络请求

2018-07-11  本文已影响94人  奔跑吧小蚂蚁

在讲解域名切花之前,先说一下废话吧,域名切换名字很自然就是基础域名的切换,很多时候因为单个服务压力过大时,会在造成请求超时,或者其他的一些请求异常错误,所以需要我们进行多域名的切换操作。

多域名切换首先需要用到是多线程,这里我选用到是GCD当然也可以采用其他的方式。
同时异步并发多个网络请求,当请求完毕后,如果全部请求失败 我们给予通过,如果只有全部通过我们则选择第一个请求成公的域名地址。

当然我们有一些需要注意的点,首先我们进行域名切换时相当于多个线程同时访问同一个请求变量,多个线程同时访问一个变量时,我们知道是一定会造成这个变量的异常,所以此处我添加的一个自旋锁 ,也就时GCD中的信号量,这样可以保证每个当多个线程同时访问同一个变量时,可以让其先执行完一个,在执行下一个,但是其造作顺序依然是不固定的。也符合异步并发的要求。

另外我们在请求全部结束之后需要获取通知 ,进行提示或者UI上的变动就需要用到“ dispatch_group_t”通知相关的内容。

好了废话就到这里直接看代码吧。

- (void)asyncConcurrent{
    WeakSelf
    //域名数据组,从本地获取
    NSArray *websiteArray = [ZFURLDefault get_websiteArray];
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    for (int i = 0; i<websiteArray.count; i++) {
        dispatch_group_enter(group);
        dispatch_group_async(group, queue, ^{
            NetworkURLString = websiteArray[i];
            NSString *url = [NSString stringWithFormat:@"%@/api/v1/appversion",websiteArray[i]];
            NSMutableDictionary *params = [NSMutableDictionary dictionary];
            params[@"versionCode"] = [RWSimpleTool getCFBundleVersion];
            params[@"packageName"] = [RWSimpleTool getBundleidentifier];
            [ZFNetTool  GET:url params:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
                dispatch_group_leave(group);
                ZFLog(@"\n---------------线程成功 i:%d:%@",i,url);
                //isExecute默认值为NO,当第一次请求成功后赋值为YES不再调用
                if (!weakSelf.isExecute) {
                    weakSelf.isExecute = YES;
                    // NetworkURLString域名基址
                    NetworkURLString = websiteArray[i];
                }
            } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
                ZFLog(@"\n---------------线程失败:%@",url);
                dispatch_group_leave(group);
            }];
            dispatch_semaphore_signal(semaphore);
        });
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        for (int i = 0; i<websiteArray.count; i++) {
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        }
        ZFLog(@"\n---------------执行完毕可进行自己需要的操作了");
    });
}

这里的网络请求改成自己写的网络请求就可以了,另外一点需要注意的是 如果没有增加自旋锁的功能,当你测试内存时你会发现会内存泄漏,因为我这边的项目是只在启动的时候调用一次,功能正常也不会崩溃,但是毕竟是一个风险,所以枷锁是必不可少的。

希望随你有用~

上一篇下一篇

猜你喜欢

热点阅读