一.GCD基础概念:{
1 .概念:Grand Central Dispatch,纯C语言的,提供了很多非常强大的函数;
2 .GCD优势:{
a.GCD为多核运算的并行运算提供解决方案;
b.GCD会自动利用更多的CPU内核(如2核/4核);
c.GCD会自动管理线程的生命周期(创建/调度/销毁);
d.只需告诉GCD做什么任务,不用编写管理代码;}
3 .GCD的核心:'将任务添加到队列'{
a. 任务:执行什么操作;
b. 队列:用来存放任务;}
4 .GCD的使用的两个步骤:{
a .创建任务:确定要做的事情,用Block封装任务;
b .将任务添加到队列中:{
GCD"自动"从队列中将任务取出,放到对应的线程中执行.
任务的去除遵循队列的"FIFO"原则:'先进先出,后进后出'
}}}
二.队列和任务:{
(一).队列:{
1. 串行队列:'DISPATCH_QUEUE_SERIAL'{
- 定义:
dispatch_queue_t queue = dispatch_queue_create("队列标识符", DISPATCH_QUEUE_SERIAL);
- 串行对类让任务"一个一个有序"的执行,一个执行完后,再执行下一个
- 同时只能调度一个任务执行;}
2. 并发队列:'DISPATCH_QUEUE_CONCURRENT'{
- 定义:
dispatch_queue_t queue = dispatch_queue_create("队列标识符", DISPATCH_QUEUE_CONCURRENT);
- 可以让多任务"同时(并发)"执行,自动开启多个线程同时执行多个任务;
- 并发队列的并发功能只有内部的任务是"异步任务"的时候,才有效}}
(二).任务:{
1. 同步执行任务:在'当前线程'中'依次'执行任务{
dispatch_sync(dispatch_queue_t queue,dispatch_block_t block)
- queue:队列
- block:任务}
2. 异步执行任务:'新开线程',在新线程中执行任务{
dispatch_async(dispatch_queue_t queue.dispatch_block_t block);
- queue:队列
- block:任务}}}
三.延时操作:延迟多少纳秒,在哪个队列中调度执行哪个任务{
- 函数:dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block)
- 参数:{
a.dispatch_time_t 'when':延迟的时间;
b.dispatch_queue_t 'queue':执行任务的队列;
c.dispatch_block_t 'block':线程要执行的任务;}}
四.队列和任务组合{
- 串行队列 + 同步任务:{
a. "没有"开新线程,在当前线程中执行;
b. 线程内任务"顺序"执行;
c. "执行完"线程中所有任务后,执行线程中其他任务;} - 串行队列 + 异步任务:{
a. "新开"一条线程,原因看下一条;
b. 新线程中前一个任务执行完后执行后一个任务;
c. 原来线程中的任务异步执 ,"不必"等待新任务执行完;} - 并发队列 + 同步任务:{
a. "没有"开新线程,在当前线程中执行;
b. 线程内任务"顺序"执行;
c. "执行完"线程中所有任务后,执行线程中其他任务;} - 并发队列 + 异步任务:{
a. 开启"多条"新线程;
b. 线程内任务"随机"执行;
c. 线程外任务"异步"执行;} - 总结:{
- 先看任务:如果是同步任务,则不开新线程,任务依次执行,线程内任务执行完后执行线程外任务;
- 如果是异步任务,看队列:串行队列新建一个线程,新线程内任务依次执行,原线程中任务无需等待;
- 如果是并发队列,开启多条线程,新线程内任务随机执行,原线程内任务无需等待,在原线程中执行
}}
五.主队列:dispatch_get_main_queue(){
1.特点:{
a. 专门用来在主线程上调度任务的队列;
b. 不会开启新线程;
c. 以先进先出的方式,在主线程空闲的时候才会调度队列中的任务在主线程中执行;
d. 如果当前主线程有正在执行的任务,那么无论主队列中当前被添加了什么任务,都不会被调度
e. 主队会随着主程序启动一起创建,只需获取,不用创建;
}
2.组合:{
a. 主队列 + 异步队列:先执行队列外的主线程中的任务,待主线程中任务都执行完了以后再执行队列中的任务;
任务1 -> dispatch_async{dispatch_get_main_queue(),^ (任务2)} ->任务3
执行顺序:任务1 -> 任务3 -> 任务2;
b. 主队列 + 同步任务 = 锁死:
原因分析:主线程在等待同步任务执行完,同步任务中的主队列在等待主线程中的任务执行完毕;
解决办法:将主队列的同步任务放到子线程中(这么作,何必呢?);}}
六.全局队列:dispatch_get_global_queue(0, 0){
- 定义:全局并发队列,系统提供的,工作表现和并发队列一致;
- 全局队列:并发队列{'比较'
a. 没有名字:有名字
b. 无论ARC还是MRC都不需要考虑释放:MRC下需要dispatch_release(q)
c. "日常开发"中推荐使用:"开发第三方框架"建议使用并发}}
七.GCD应用:{
建立依赖:同步任务{
//获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
//在全局队列中执行异步任务,防止耗时任务在主线程中执行
dispatch_async(queue, ^{
//建立'任务1','任务2','任务3'的依赖关系,1,2,3依次完成
dispatch_sync(queue, ^{任务1});
dispatch_sync(queue, ^{任务2});
...
dispatch_sync(queue, ^{任务3});
//回到主线程刷新UI(使用异步任务,防止卡顿)
dispatch_async(dispatch_get_main_queue, ^{主线程刷新UI})
})
}-
一次性执行:dispatch_once_t{
内部有一把锁,保证内部代码只执行一次:
a. 'once用于设计单例模式:'{
static NetworkTool *instance;
//敲dispatch_once会有提示
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[NetworkTool alloc] init];
});return instance;
}
b. '互斥锁单例设计模式:'{
static AccountManager *manager;// 为保证在多线程的环境下,线程的安全,所以添加了一把互斥锁
// 但是互斥锁的性能有点儿差
@synchronized(self) {
// 判断内存中有没有这个对象,如果没有,就创建
if (manager == nil) {
manager = [[AccountManager alloc] init];
}
}
return manager;}
c. 比较:性能once更好,操作更简单;} 调度组
}