iOS GCD group 多请求异步 semaphore 多请求同步

在做项目的时候往往会出现多图上传的功能,而恰巧服务器可能只支持单张上传,所以你要遍历请求,而全部上传完成后可能还要刷新列表啊或者给个提示框啊等需求。
有些人可能会一个网络请求成功回调里面再嵌套一个,类推,如果上传9张图就要嵌套9次,很显然这样的代码看上去有点low而且非并发耗时比较慢,推荐使用gcd group 组。话不多说上代码:

//创建一个组
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i <9; I++)
{//模仿多个网络请求
    dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
        //异步网络请求
        
        int x = arc4random() % 5;
        //模拟网络请求快慢不确定的情况
        sleep(x);
        
        NSLog(@"group 请求成功OR请求失败 %d!",i);
    });
}
NSLog(@"group开始 网络请求!");

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    //网络请求完毕 回到主线程更新UI 或者做些其它的操作
    NSLog(@"group所有请求完毕!!!");
});

使用dispatch_group_async函数将多个任务关联到一个Dispatch Group和相应的queue中,group会并发地同时执行这些任务。而且Dispatch Group可以用来阻塞一个线程, 直到group关联的所有的任务完成执行调用dispatch_group_notify方法,这样就达到了想要的效果。

iOS GCD group 多请求异步 semaphore 多请求同步_第1张图片
ABF94C9D-3542-4C6C-A30C-2BA6DCDDB02B.png

当然你也可以不使用dispatch_group_async函数,转而使用dispatch_group_enter和dispatch_group_leave,注意这里要配套使用哦。
dispatch_group_enter:通知group,下面的任务马上要放到group中执行了。
dispatch_group_leave:通知group,任务完成了,该任务要从group中移除了。

//创建一个组
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i <9; I++)
{//模仿多个网络请求
    
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //异步网络请求
        
        int x = arc4random() % 5;
        //模拟网络请求快慢不确定的情况
        sleep(x);
        NSLog(@"group 请求成功OR请求失败 %d!",i);
        
        dispatch_group_leave(group);
    });
}
NSLog(@"group开始 网络请求!");

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    //网络请求完毕 回到主线程更新UI 或者做些其它的操作
    NSLog(@"group所有请求完毕!!!");
});
iOS GCD group 多请求异步 semaphore 多请求同步_第2张图片
A27BFDF3-170D-40D9-BD7F-3802FAF82D56.png

还有一种情况,比如要做一个相册功能,也是多图上传,但是要有规律按顺序上传。这里就推荐使用dispatch_semaphore_t 信号量,也是利用线程阻塞来实现。直接上代码:

//创建一个信号量 数值为1
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
for (int i = 0; i<9; I++)
{//模仿多个网络请求
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        //执行dispatch_semaphore_wait 信号量数值 -1.
        //当i为0此时的信号量数值为0, 当此时的信号量大于等于0继续执行wait函数下面的语句.
        //当i为1此时的信号量数值为-1, 阻塞当前线程 阻塞时长为DISPATCH_TIME_FOREVER, 不执行wait函数下面的语句.
        //只有等到执行i为0 的 dispatch_semaphore_signal 方法执行, 信号量数值+1 为0, 唤醒 继续执行wait函数下面的语句.
        //以此类推循环.
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        //异步网络请求
        int x = arc4random() % 5;
        //模拟网络请求快慢不确定的情况
        sleep(x);
        
        //信号量数值+1
        dispatch_semaphore_signal(semaphore);
        
        NSLog(@"semaphore 请求成功OR请求失败 %d!",i);
        
    });
}
NSLog(@"semaphore开始 网络请求!");
iOS GCD group 多请求异步 semaphore 多请求同步_第3张图片
177A6461-5459-4E3D-BB4C-99783FE84515.png

如果需要两者结合使用呢也是可以的,这样即能按顺序上传,又能在上传后收到通知做一些提示或者其它操作,请看代码:

dispatch_group_t group = dispatch_group_create();
//创建一个信号量 数值为1
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

for (int i = 0; i<9; I++)
{//模仿多个网络请求
    dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
        
        //执行dispatch_semaphore_wait 信号量数值 -1.
        //当i为0此时的信号量数值为0, 继续执行wait函数下面的语句.
        //当i为1此时的信号量数值为-1, 阻塞当前线程 阻塞时长为DISPATCH_TIME_FOREVER, 不执行wait函数下面的语句.
        //只有等到执行i为0 的 dispatch_semaphore_signal 方法执行, 信号量数值+1 为0, 唤醒 继续执行wait函数下面的语句.
        //以此类推循环.
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        //异步网络请求
        int x = arc4random() % 5;
        //模拟网络请求快慢不确定的情况
        sleep(x);
        
        //信号量数值+1
        dispatch_semaphore_signal(semaphore);
        
        NSLog(@"groupSemaphore 请求成功OR请求失败 %d!",i);
        
    });
}

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    //网络请求完毕 回到主线程更新UI 或者做些其它的操作
    NSLog(@"groupSemaphore所有请求完毕!!!");
});

NSLog(@"groupSemaphore开始 网络请求!");
iOS GCD group 多请求异步 semaphore 多请求同步_第4张图片
8374502A-9C0C-4A0D-ABE6-9B1C9E7949F1.png

想要顺序(同步)执行异步任务的话,可以把一个个异步任务放在串行队列里面去执行,代码如下:

dispatch_queue_t queue = dispatch_queue_create("serial",DISPATCH_QUEUE_SERIAL);
///在串行队列中 执行第一个异步任务
dispatch_async(queue, ^{
    NSLog(@"1---%@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:5];
    NSLog(@"xxxxxxxxxxxxxx");
});
///在串行队列中 执行第二个异步任务
dispatch_async(queue, ^{
    NSLog(@"2---%@", [NSThread currentThread]);
});
///在串行队列中 执行第三个异步任务
dispatch_async(queue, ^{
    NSLog(@"3---%@", [NSThread currentThread]);
});
iOS GCD group 多请求异步 semaphore 多请求同步_第5张图片
E3F126184247B6AF82003F339439F266.jpg

如果有不同见解欢迎讨论,有错误还请指出,博主加以改正,谢谢!
转载请说明出处,代码在这里。请不要吝啬您的star

你可能感兴趣的:(iOS GCD group 多请求异步 semaphore 多请求同步)