dispatch_group_async
队列组, 异步执行, 等所有任务执行完毕, 会执行dispatch_group_notify, 这种之前应用场景是同时异步下载多张图片的操作, 等到所有图片现在完毕, 拿到图片进行拼接.
dispatch_group_t group = dispatch_group_create();
NSMutableArray *mua = [NSMutableArray array];
for (YSPatientModel *model in groupModel.members) {
if (model.pic) {
dispatch_group_enter(group);
[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:model.pic] options:0 progress:nil completed:^(UIImage* image, NSError* error, SDImageCacheType cacheType, BOOL finished, NSURL* imageURL) {
if (image) {
[mua addObject:image];
}
// NSLog(@"线程%@",[NSThread currentThread]);
dispatch_group_leave(group);
}];
}
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
UIImage *resultImage = [UIImage composeHeaderImageWithConstrainWH:self.groupIconImg.bounds.size.width imagePathArray:mua backgroundColor:RGB(236, 236, 236)];
self.groupIconImg.image = resultImage;
});
dispatch_barrier_async 栅栏
同一队列, 异步执行时,barrier块必须单独执行,不能与其他block并行。这只对并发队列有意义,并发队列如果发现接下来要执行的block是个barrier block,那么就一直要等到当前所有并发的block都执行完毕,才会单独执行这个barrier block代码块,等到这个barrier block执行完毕,再继续正常处理其他并发block。
dispatch_queue_t queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----2-----%@", [NSThread currentThread]);
});
// 都会等待在它前面插入队列的任务(1、2、)先执行完再执行后面的任务(3, 4)
dispatch_barrier_async(queue, ^{
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----3-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----4-----%@", [NSThread currentThread]);
});
dispatch_semaphore 信号量
防止多个线程同时操作一块资源, 控制并发。dispatch_semaphore_create 可以理解为创建的信号总量,dispatch_semaphore_signal是发送一个信号,会让信号总量加1,dispatch_semaphore_wait等待信号,让信号总量-1,当信号总量少于等于0的时候就会一直等待,否则就可以正常的执行,可以创建一个并发控制。YYCache里有用到。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 异步3个线程访问2个资源, 只分配2个资源
//任务1
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 1");
dispatch_semaphore_signal(semaphore);
NSLog(@"complete task 1");
});
//任务2
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 2");
dispatch_semaphore_signal(semaphore);
NSLog(@"complete task 2");
});
//任务3
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 3");
dispatch_semaphore_signal(semaphore);
NSLog(@"complete task 3");
});
当然, 底下 NSLock锁 一样可以实现以上操作。
NSLock锁
NSLock *lock = [[NSLock alloc]init];
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//任务1
dispatch_async(quene, ^{
[lock lock];
NSLog(@"run task 1");
sleep(5);
[lock unlock];
NSLog(@"complete task 1");
});
//任务2
dispatch_async(quene, ^{
[lock lock];
NSLog(@"run task 2");
[lock unlock];
NSLog(@"complete task 2");
});
// 打印结果
// 2017-08-10 16:29:44.792 GCDSemaphore[8153:2775304] run task 1
// 2017-08-10 16:29:49.797 GCDSemaphore[8153:2775302] run task 2
// 2017-08-10 16:29:49.797 GCDSemaphore[8153:2775304] complete task 1
// 2017-08-10 16:29:49.797 GCDSemaphore[8153:2775302] complete task 2
当任务1锁住之后,任务2会一直等待5s后等任务1将锁设置为unlock后,才会执行run task 2。如果不unlock, 那么任务2永远不会执行