一. GCD基本知识
- 两个核心概念 队列和任务
- 同步函数和异步函数
二. GCD基本使用
- 异步函数+并发队列 : 开启多条线程, 并发执行任务
- 异步函数+串行队列 : 开启一条线程, 串行执行任务
- 同步函数+并发队列 : 不开启线程, 串行执行任务
- 同步函数+串行队列 : 不开启线程, 串行执行任务
- 异步函数+主队列 : 不开启线程,在主线程上串行执行任务
- 同步函数+主队列 : 不开线程, 串行执行任务(注意发生死锁)
- 注意同步函数和异步函数在执行顺序上的差异
三. GCD线程间通信
//获取一个全局队列
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
//开启一个线程 把下载图片的操作放在子线程中处理
dispatch_async(queue,^{
//下载图片
NSURL *url = [NSURL URLWithString@"图片URL地址"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
NSLog(@"下载操作所在的线程__%@",[NSThread currentThread]);
//回到主线程刷新UI
dispatch_async(dispatch_get_main_queue(),^{
self.imageView.image =image;
//打印查看当前线程
NSLog(@"刷新UI-----%@",[NSThread currenThread);
});
});
四. GCD其他常用函数
栅栏函数 (控制任务的执行顺序)
dispatch_barrier_async(queue,^{
NSLog (@"----dispatch_barrier_async-");
});延迟执行 (延迟.控制在哪个线程执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"---%@",[NSThread currentThread]);
});-
一次性代码 (注意不能放到懒加载)
- (void)once
{
//整个程序运行过程中只会执行一次
//onceToken用来记录该部分的代码是否被执行过
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{NSLog(@"-----"); });
快速迭代 (开多个线程并发完成迭代操作)
dispatch_apply(subpaths.count, queue, ^(size_t index) {
});队列组 (同栅栏函数)
//创建队列组
dispatch_group_t group = dispatch_group_create();
//队列组中的任务执行完毕之后,执行该函数
dispatch_group_notify(dispatch_group_t group,dispatch_queue_t queue,dispatch_block_t block);进入群组和离开群组
dispatch_group_enter(group);//执行该函数后,后面异步执行的block会被gruop监听
dispatch_group_leave(group);//异步block中,所有的任务都执行完毕,最后离开群组
//注意:dispatch_group_enter|dispatch_group_leave必须成对使用
五. 使用Crearte函数创建的并发队列和全局并发队列的主要区别:
1)全局并发队列在整个应用程序中本身是默认存在的并且对应有高优先级、默认优先级、低优先级和后台优先级一共四个并发队列,我们只是选择其中的一个直接拿来用。而Create函数是实打实的从头开始去创建一个队列。
2)在iOS6.0之前,在GCD中凡是使用了带Create和retain的函数在最后都需要做一次release操作。而主队列和全局并发队列不需要我们手动release。当然了,在iOS6.0之后GCD已经被纳入到了ARC的内存管理范畴中,即便是使用retain或者create函数创建的对象也不再需要开发人员手动释放,我们像对待普通OC对象一样对待GCD就OK。
3)在使用栅栏函数的时候,苹果官方明确规定栅栏函数只有在和使用create函数自己的创建的并发队列一起使用的时候才有效(没有给出具体原因)