因为项目要实现阿里云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);