这是我参与「第四届青训营 」笔记创作活动的第3天
1、任务和队列
- 步骤
- 创建任务:需要做什么事情,要执行的操作
- 将任务存放到队列中,GCD会自动将队列的任务取出,放到对应的线程中去执行,遵循先进先出原则
2、开启子线程
- 1、创建一个队列
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
- 2、创建一个任务
dispatch_block_t task = ...;
- 3、异步执行
dispatch_async(queue, task);
//第一个参数是队列,第二个参数是任务
- 用CGD异步加载网络图片
//开启异步加载图片信息
dispatch_async(dispatch_get_global_queue(0,0),^{
UIImage *image = [UIImage imageWithData:data];
//回到主线程更新UI
dispatch_sync(dispatch_get_main_queue(),^{
self.imageView.image = image;
[self.imageView sizeToFit];
},
};
3、队列
- 队列两大类型
- 并发队列
- 可以让多个任务同时执行(自动开启多个线程同时执行任务)
- 并发功能只有在异步(dispatch_async)函数下才有效
- 串行队列
- 让任务一个接一个按顺序执行
- 主队列
- 全局队列
- 并发队列
(1)串行队列
- 串行同步执行(在当前线程执行,不开新线程)
创建串行队列 DISPATCH_QUEUE_SERIAL参数表示串行队列
dispatch_queue_t queue = dispatch_queue_create("队列名",DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue,^{
NSLog("");//在当前线程执行(不一定是主线程)
});
- 串行异步执行(会开启线程,但是只开启一个线程,有顺序执行)
//创建串行队列DISPATCH_QUEUE_SERIAL
dispatch_queue_t queue = dispatch_queue_create("名字",DISPATCH_QUEUE_SERIAL);
dispatch_async(queue,^{
NSLog("");(在一个新线程执行)
});
(2)并行队列
- 并行同步执行(不开线程,在当前线程执行)与串行队列效果一样
//创建并行队列DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t queue = dispatch_queue_create("",DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue,^{
NSLog("");
});
- 并行异步执行(开启多个线程,任务进行无顺序,程序性能高)
//创建并行队列DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t queue = dispatch_queue_create("",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue,^{
NSLog("");//开启多个线程,无序
});
(3)主队列 (全局串行队列)
- 特点
- 先按顺序执行完主线程上的代码,才会执行主队列的任务
- 主队列,异步执行
dispatch_async(dispatch_get_main_queue(),^{
NSLog("");//在主线程当中顺序执行
}
- 主队列,同步执行
- 在主线程中执行主队列同步执行会造成死锁
- 主队列上的任务需要等待主线程的代码执行完,但是主线程上的代码是主队列上的任务,造成矛盾,死锁
//只能在在子线程中使用主队列同步执行
dispatch_sync(dispatch_get_main_queue(),^{
NSLog("");//在主线程当中顺序执行
}
- 主队列和串行队列的区别
- 串行队列:必须等待一个任务执行完成,在调度另一个任务
- 主队列:如果主线程代码还未执行完,主队列将不会调度任务,同时满足串行队列
(4)全局队列
- 全局队列本质上是并发队列
dispatch_get_global_queue(0,0) - 全局队列和并行队列的区别
- 并行队列有名称,可以跟踪错误,而全局队列没有
- 在MRC中,并行队列是create,需要手动release,而全局队列不需要
dispatch_get_global_queue(0,0)参数- 第一个参数:表示优先级,0为默认优先级
- 代表了线程的调用优先顺序
4、同步任务
- 当有多个耗时操作的任务需要按顺序执行
- 开辟一个子线程
- 在子线程中使用同步执行方法(与串行队列效果相同)
5、Barrier阻塞
- 主要用于在大量异步操作完成后,同一对非线程安全对象进行更新
- 适合于大规模的I/O操作
- 等待该队列中的其他任务都执行完,才会执行阻塞中的代码
dispatch_barrier_async(dispatch_get_global_queue(0,0),^{
//队列中最后执行的代码
});
6、调度组
//创建组
dispatch_group_t group = dispatch_group_create();
//队列
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
//该组有多个异步任务
dispatch_group_async(group,queue,^{
NSLog("1");
});
dispatch_group_async(group,queue,^{
NSLog("2");
});
dispatch_group_async(group,queue,^{
NSLog("3");
});
//当该组的所有异步任务都执行完成后,才执行
dispatch_group_notify(group,dispatch_get_main_queue(),^{
NSLog("");
});