dispatch_group_t与dispatch_semaphore_t和dispatch_group_enter

因为项目要实现阿里云OSS上传,并且不限制图片的数量,上传成功一张图片后会返回一个URL,于是就想到了用GCD的group与全局并发队列global_Queue,搭配dispatch_group_notify使用:

NSMutableArray<NSString *> *urls = [NSMutableArray array];
 dispatch_group_t group1 = dispatch_group_create();
     dispatch_queue_t globQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    for (UIImage *image in iamges) {
        dispatch_group_async(group1, globQueue, ^{
            [self upLoadImage:image block:^(id url) {
                [urls addObject:url];
                NSLog(@"结束第%ld个图片___线程:%@",[iamges indexOfObject:image],[NSThread currentThread]);
            }];
        });
    }
    dispatch_group_notify(group1, globQueue, ^{
        block(urls);
    });

发现到dispatch_group_notify时urls是空,于是我就查原因,经过调试后发现,上传到阿里云OSS的请求是异步操作,于是dispatch_group_async的block执行完毕后然而upLoadImage的block还没有返回呢。这样for循环结束后,所有的dispatch_group_async的block都执行完毕,图片还没有上传成功的,这样就直接通知了dispatch_group_notify所有的线程执行完毕,导致urls为空。
于是想到了用dispatch_group_enter与dispatch_group_leave:

dispatch_group_t group1 = dispatch_group_create();
     dispatch_queue_t globQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    for (UIImage *image in iamges) {
        dispatch_group_enter(group1);
        [self upLoadImage:image block:^(id url) {
            [urls addObject:url];
            NSLog(@"结束第%ld个图片___线程:%@",[iamges indexOfObject:image],[NSThread currentThread]);
            dispatch_group_leave(group1);
        }];
    }
    dispatch_group_notify(group1, globQueue, ^{
        block(urls);
    });

上边说过由于upLoadImage是异步操作,所以直接省了dispatch_group_async,
果然这样写后,urls能正常获得。dispatch_group_enter告诉group下边的操作是要加入group中,dispatch_group_leave告诉group当前操作移除group,当所有的操作移除group者会通知dispatch_group_notify。这样就实现了图片上传到OSS的多线程并发。
由于没有限制传图片的一次多少张,所以又想到了dispatch_semaphore_t即信号量:

在GCD中有三个函数是semaphore的操作,分别是:
  dispatch_semaphore_create   创建一个semaphore
  dispatch_semaphore_signal   发送一个信号
  dispatch_semaphore_wait    等待信号

所以代码改成:

dispatch_group_t group1 = dispatch_group_create();
     dispatch_queue_t globQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     dispatch_semaphore_t semaphore1 = dispatch_semaphore_create(10);//每次最多开11个
    for (UIImage *image in iamges) {
        dispatch_group_enter(group1);
        [self upLoadImage:image block:^(id url) {
            [urls addObject:url];
            NSLog(@"结束第%ld个图片___线程:%@",[iamges indexOfObject:image],[NSThread currentThread]);
            dispatch_group_leave(group1);
            dispatch_semaphore_signal(semaphore1);//信号量+1
        }];
        dispatch_semaphore_wait(semaphore1, DISPATCH_TIME_FOREVER);//信号量-1
    }
    dispatch_group_notify(group1, globQueue, ^{
        block(urls);
    });

这样一次最大开辟11个线程,等每次for循环dispatch_semaphore_wait都会信号量减去1,当信号量小于0时者会等待子线程执行完后的 dispatch_semaphore_signal信号量加1这样子线程一直维持在小于等于11个。等全部执行完通知dispatch_group_notify执行block(urls);

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容