总结
GCD的全称是Grand Central Dispatch,GCD 为了替代NSThread,充分利用苹果设备的多核设备,生命周期自动管理,是纯C语言,提供了非常直观和用户理解和习惯的函数,用DISPATCH_QUEUE_SERIAL,和 DISPATCH_QUEUE_CONCURRENT 控制串行和并行,用sync和async控制同步和异步。
1.基本使用
//串行队列创建 DISPATCH_QUEUE_SERIAL
dispatch_queue_t serial =
dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
//并行队列创建 DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t concurrent =
dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
//同步
dispatch_sync(serial/concurrent , ^{
});
异步
dispatch_async(serial/concurrent, ^{
});
GCD的线程代码在表达串行,并行,同步,异步,代码结构清晰,层次分明,非常贴近,我们对变量控制的理解。
2.特殊函数使用
2.1 栅栏函数之前的执行完毕之后,执行栅栏函数,然后在执行栅栏函数之后的
dispatch_barrier_async(concurrent, ^{
NSLog(@"我是一个栅栏函数");
});
2.2 延迟
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(2*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"after %@",[NSThread currentThread]);
});
2.3 onceToken记录代码是否被执行过,通常用来写单例
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"执行一次");
});
2.4 快速迭代:开启多条线程,并发执行,比普通的循环快
dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
NSLog(@"%zu",index);
});
2.group使用
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{
NSLog(@"下载照片一");
});
dispatch_group_async(group, queue, ^{
NSLog(@"下载照片二");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"照片一和照片二合成一张照片");
});
3.死锁
//在UI线程中
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"task1-%@",[NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"task2-%@",[NSThread currentThread]);
});
NSLog(@"task3-%@",[NSThread currentThread]);
task1是在主线程中执行,而主线程是串行队列,定义的queue队列也是主队列, dispatch_sync是同步执行的标志,意思是必须等待block返回,才能执行task3,而当前主队列中正在被task1执行,必须等待完成task3完成后才能释放,这就造成了task3等待block完成返回,block等待task3完成释放主队列而相互等待的循环中死锁
4.一些容易混淆的点
同步 并发 串行: 都是没有开启新线程,都是串行执行任务,因为要和主线程同步
穿行任务不一定只在一个线程中执行,并发的任务不一定在多个线程中,任务和线程不是一一绑 定执行的关系,而取决于线程池和CPU的调度。