GCD使用
名词
-
串行(Serial)与 并发(Concurrent)
任务串行,意味着在同一时间,有且只有一个任务被执行,即一个任务执行完毕之后再执行下一个任务。
任务并发,意味着在同一时间,有多个任务被执行。 -
同步(Synchronous)与 异步 (Asynchronous)
同步,意味着在当前线程中执行任务,不具备开启新的线程的能力。
异步,在新的线程中执行任务,具备开启新的线程的能力。
在 GCD 中,这些术语描述当一个函数相对于另一个任务完成,此任务是该函数要求 GCD 执行的。一个同步函数只在完成了它预定的任务后才返回(阻塞当前Queue,先执行传入的Queue)。
一个异步函数,刚好相反,会立即返回,预定的任务会完成但不会等它完成。因此,一个异步函数不会阻塞当前线程去执行下一个函数。
GCD获取的队列
//得到运行在主线程的mainQueue
dispatch_queue_t mainQueue=dispatch_get_main_queue();
//得到全局队列(全局的并行队列)
dispatch_queue_t globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建一个串行队列
dispatch_queue_t serialQueue=dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);
//创建一个并行队列
dispatch_queue_t concurrentQueue=dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);
GCD的使用
基本使用
//同步执行
dispatch_sync(queue, ^{
// do something
});
//异步执行
dispatch_async(queue, ^{
// do something
});
// 一次性执行:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// do something
});
// 延迟2秒执行:
double seconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC);
dispatch_after(popTime, queue, ^(void){
// do something
});
使用group
// 创建group
dispatch_group_t group=dispatch_group_create();
dispatch_group_async(group, queue, ^{
//任务一
});
dispatch_group_async(group, queue, ^{
//任务二
});
dispatch_group_notify(group, queue, ^{
//任务都结束调用
});
单例
+ (Manager *)sharedManager
{
static Manager *sharedManagerInstance = nil;
static dispatch_once_t onct;
dispatch_once(&onct, ^{
sharedManagerInstance = [[self alloc] init];
});
return sharedManagerInstance;
}
串行并行队列与同步异步执行的各种组合
1、 异步函数 + 并行队列
可以新建线程,各线程也是并发执行的。
结论:在队列中的任务“在多个线程并发”执行
2、 同步函数+并发队列
因为是同步函数,所以不新建线程,只要是同步函数,就不会新建线程。
并发队列与否,并不影响同步函数的创建,因为本身就不能多创建线程,也就不存在并发。
结论:在队列中的任务“one by one”执行
3、异步函数+串行队列
这个搭配可以新建线程,但是因为是串行队列,所以实际上也只是开了一条新线程,做完一个,再做另一个。
结论:在队列中的任务“在新线程one by one”执行
4、同步函数+串行队列
这样既不会开新线程,也是串行执行的。
结论:在队列中的任务“one by one”执行
注意:
当串行queue中调用dispatch_sync传入的还是当前queue,会造成死锁。
例如:
dispatch_async(serialQueue1, ^{
//serialQueue1队列中调用dispatch_sync传入的还是serialQueue1.
//dispatch_async创建的新线程会死锁
dispatch_sync(serialQueue1, ^{
NSLog(@"1554654-----%@",[NSThread currentThread]);
});
});
或:
//主线程中调用会死锁
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"1-----%@",[NSThread currentThread]);
});
原因:
dispatch_sync会阻塞当前queue等待传入的queue执行完返回才会继续。而传入的还是当前queue。需要执行的block被放到传入queue的队尾等待执行。而queue还在等待dispatch_sync函数返回。block永远不会执行,dispatch_sync永远不会返回,造成死锁