GCD dispatch
GCD dispatch
同步 && 异步 && 串型 && 并发
- 同步:没有开启新线程的能力
- 所有任务都在 begin 和 end 之间执行
- 串型和并发效果一样,都不开启新线程
- 异步:有开启新线程的能力,但是否开启视情况而定
- 若加入串型,所有任务都在 begin 和 end 之后逐个执行
- 若加入并发,所有任务都在 begin 之后执行
- 串型:加入队列的逐个执行
- 并发:需要与异步配合,才能开启新线程并发执行。否则加入的队列逐个执行
同步执行 + 并发队列
- 无法开启新线程
- 任务加入队列后直接执行,然后再执行后面内容
异步执行 + 并发队列
- 可以开启多个线程
- 任务加入队列后直接执行,可以多个任务同时执行
异步执行 + 并发队列
(类似于同步执行 + 并发队列)
- 无法开启新线程
- 任务加入队列后直接执行,然后再执行后面内容
dispatch_barrier
- 控制某些任务全部执行完成后再进行下面的任务
- 适用场景:异步 + 并发
dispatch_barrier_async(queue, ^{
// 追加任务 barrier
[NSThread sleepForTimeInterval:5]; // 模拟耗时操作
NSLog(@"barrier---%@",[NSThread currentThread]);// 打印当前线程
})
dispatch_after
- 加入主队列并准备 2 秒后执行。
- 若 2s 后主线程未占用,则直接执行。若占用,则等待空闲时立即执行。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2.0 秒后异步追加任务代码到主队列,并开始执行
NSLog(@"after---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_apply
- 快速迭代方法。
- 相当于 for 循环,建议用在并发队列。
dispatch_apply(6, queue, ^(size_t index) {
NSLog(@"%zd---%@",index, [NSThread currentThread]);
});
dispatch_group
dispatch_group_notify
- 把任务都异步并发的加入 group 中,等前面的都执行完才执行 dispatch_group_notify
- (void)groupNotify {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"group---begin");
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任务 1
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任务 2
[NSThread sleepForTimeInterval:2.5]; // 模拟耗时操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步任务 1、任务 2 都执行完毕后,回到主线程执行下边任务
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"group---end");
});
}
dispatch_group_enter dispatch_group_leave
- 通过 dispatch_group_enter、dispatch_group_leave 控制执行,在group内部会有一个计数器,调用dispatch_group_enter后,该计数器会 +1,调用 dispatch_group_leave后该计数器会 -1,当计数器为 0 时,则主动调用dispatch_group_notify 的 block,否则一直处于等待中。(其他任务开异步加入 queue 即可,不用加入 group)
- (void)groupEnterAndLeave {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"group---begin");
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(group);
dispatch_async(queue, ^{
// 追加任务 1
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印当前线程
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
// 追加任务 2
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印当前线程
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程.
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"group---end");
});
}
dispatch_semaphore 信号
#pragma mark - 保证线程间同步
dispatch_queue_t que = dispatch_queue_create("com.vc.downloadQueue", DISPATCH_QUEUE_SERIAL);
// 设置信号量为 3
dispatch_semaphore_t semaphore = dispatch_semaphore_create(3); //
dispatch_async(que, ^{
// 若 signal 0,则 wait forever 否则 signal - 1 并执行后面的代码
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
// singal + 1
dispatch_semaphore_signal(self.semaphore);
#pragma mark - 为线程加锁
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
for (int i = 0; i < 100; i++) {
dispatch_async(queue, ^{
// 相当于加锁
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"i = %zd semaphore = %@", i, semaphore);
// 相当于解锁
dispatch_semaphore_signal(semaphore);
});
}
主线程获取方法
dispatch_queue_t queue = dispatch_get_main_queue();
获取默认并发队列方法
- 调用时,先执行 dispatch ,后执行 end
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!