GCD的使用

来源:互联网 发布:四川大学校内网络电视 编辑:程序博客网 时间:2024/05/30 13:42

1.什么是GCD

    GCD的全程是Crand Central Dispatch, 纯C语言的,提供了非常强大的函数API

2.GCD的核心

        核心是将任务添加到队列。

        任务:执行什么操作

        队列:用来存放任务

任务 : 任务类型决定的是"执行"的方式

     异步(dispatch_async())

     特点 : 在子线程中执行,会新开线程执行

     同步(dispatch_sync())

     特点 : "当前"线程执行,不会新开线程执行,同步任务间是有序执行的

 

 队列 : 决定了任务的"调度"的方式

     串行队列

     特点 : 串行队列里面的任务(无论什么任务),都是按顺序依次调度执行的,前面一个任务不"执行完",后面的任务不会被调度执行


3.GCD常用代码

        延迟操作+简写

  1. - (void)after {
  2.    
  3.    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  4.        NSLog(@"延迟操作执行");
  5.    });
  6.    
  7. }

         延迟操作

  1. - (void)afterDemo
  2. {
  3.    NSLog(@"start");
  4.    
  5.    /*
  6.     参数1 : dispatch_time_t when : 延迟多长时间,精确到纳秒
  7.     参数2 : dispatch_queue_t queue : 在哪个队列
  8.     参数3 : dispatch_block_t block : 执行哪个任务
  9.     */
  10.    
  11.    // 参数1 : dispatch_time_t when : 延迟多长时间
  12.    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
  13.    // 参数2 : dispatch_queue_t queue : 在哪个队列
  14. //    dispatch_queue_t queue = dispatch_get_main_queue();
  15.    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
  16.    // 参数3 : dispatch_block_t block : 执行哪个任务
  17.    dispatch_block_t block = ^{
  18.        
  19.        NSLog(@"终于执行了 %@",[NSThread currentThread]);
  20.    };
  21.    
  22.    // 结论 : 这个函数是个异步函数
  23.    dispatch_after(when, queue, block);
  24.    
  25.    NSLog(@"mark");
  26. }


串行队列+同步任务

  1. dispatch_sync(dispatch_queue_create("zyn", DISPATCH_QUEUE_SERIAL), ^{
  2.        NSLog(@"串行+同步");
  3.    });

串行队列+异步任务

  1. dispatch_async(dispatch_queue_create("zyn", DISPATCH_QUEUE_SERIAL), ^{
  2.        NSLog(@"串行队列+异步任务");
  3.    });

并行队列+同步任务

  1. dispatch_sync(dispatch_queue_create("zyn", DISPATCH_QUEUE_CONCURRENT), ^{
  2.        NSLog(@"并发+同步队列");
  3.    });

并行队列+异步任务

  1. dispatch_async(dispatch_queue_create("zyn", DISPATCH_QUEUE_CONCURRENT), ^{
  2.        NSLog(@"并发+异步队列");
  3.    });

4.GCD主队列

主队列 : 主队列是一个"特殊"的串行队列

     特点 :

     主队列也是系统创建好的,只需要直接获取 get.

     主队列里面的任务(无论是什么任务),"一定"是在主线程中执行的.所以用来做线程间的通信

     主队列什么时候调度里面的任务执行?

     ***** 主队列里面的任务"只有在主线程空闲的时候,主队列才会调度里面的任务执行"

     提示 : (用的挺少的)如果你创建了一个任务,这个任务不需要立即执行或者要等到主线程里面所有的操作执行完再执行,那么就可以把它添加到主队列

主队列+同步任务 == 死锁

  1. #pragma mark - 主队列+同步任务 == 死锁
  2. // 一旦在主线程中把同步任务添加到主队列就造成了死锁
  3. // 在实际的开发中需要避免 "在主线程中把同步任务添加到主队列"
  4. - (void)GCDDemo2
  5. {
  6.    NSLog(@"start");
  7.    
  8.    dispatch_async(dispatch_get_global_queue(0, 0), ^{
  9.        
  10.        // 获取主队列
  11.        dispatch_queue_t main_queue = dispatch_get_main_queue();
  12.        
  13.        // 同步函数/任务只在当前子线程执行
  14.        dispatch_sync(main_queue, ^{
  15.            NSLog(@"%@",[NSThread currentThread]);
  16.        });
  17.        
  18.    });
  19. }

主队列+异步任务

  1. #pragma mark - 主队列+异步任务
  2. // 开不开线程?
  3. - (void)GCDDemo1
  4. {
  5.    // 获取主队列
  6.    dispatch_queue_t main_queue = dispatch_get_main_queue();
  7.    
  8.    // 把异步任务添加到主队列
  9.    dispatch_async(main_queue, ^{
  10.        NSLog(@"%@",[NSThread currentThread]);
  11.    });
  12.    
  13.    NSLog(@"mark");
  14. }

5.GCD全局队列

  1. // 获取全局的并发队列
  2.    /*
  3.     参数2 : 苹果不知道这个参数是干啥的,预留的,为将来的框架升级准备的
  4.     参数1 : 传入0是为了适配所有的操作系统,0标示的是默认选项
  5.     */
  6.    dispatch_queue_t global_queue = dispatch_get_global_queue(0, 0);

6.GCD调度组

基本使用

  1. /// 调度组的基本使用
  2. - (void)groupDemo1
  3. {
  4.    // 调度组
  5.    dispatch_group_t group = dispatch_group_create();
  6.    
  7.    // 队列
  8.    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
  9.    
  10.    // 把一个异步任务添加到调度组和队列里面
  11.    dispatch_group_async(group, queue, ^{
  12.        
  13.        NSLog(@"下载图片A...%@",[NSThread currentThread]);
  14.    });
  15.    
  16.    dispatch_group_async(group, queue, ^{
  17.        
  18.        NSLog(@"下载图片B...%@",[NSThread currentThread]);
  19.    });
  20.    
  21.    dispatch_group_async(group, queue, ^{
  22.        
  23.        NSLog(@"下载图片C...%@",[NSThread currentThread]);
  24.    });
  25.    
  26.    // 监听 group 里面的所有的异步任务是否执行完,如果执行完就自动的执行dispatch_group_notify这个函数
  27.    // 异步监听
  28.    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  29.        
  30.        // 写图片下载完成之后的代码
  31.        NSLog(@"刷新UI %@",[NSThread currentThread]);
  32.    });
  33.    
  34.    // DISPATCH_TIME_FOREVER : 监听group里面的任务是否都执行完,直到永远(不执行完,后面的代码都不执行)
  35.    // 阻塞
  36. //    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
  37.    
  38.    NSLog(@"mark");
  39. }

实现原理

  1. /// 调度组实现原理
  2. - (void)groupDemo2
  3. {
  4.    // 调度组
  5.    dispatch_group_t group = dispatch_group_create();
  6.    
  7.    // 队列
  8.    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
  9.    
  10.    // 下载图片A
  11.    // 1.为图片A的下载操作,向group里面添加标记
  12.    dispatch_group_enter(group);
  13.    // 2.实现异步下载
  14.    dispatch_async(queue, ^{
  15.        NSLog(@"下载图片A...%@",[NSThread currentThread]);
  16.        
  17.        // 3.这个图片下载完成,说明任务结束,那么把这个任务对应的标记从group移除
  18.        dispatch_group_leave(group);
  19.    });
  20.    
  21.    // 下载图片B
  22.    // 1.为图片B的下载操作,向group里面添加标记
  23.    dispatch_group_enter(group);
  24.    // 2.实现异步下载
  25.    dispatch_async(queue, ^{
  26.        NSLog(@"下载图片B...%@",[NSThread currentThread]);
  27.        
  28.        // 3.这个图片下载完成,说明任务结束,那么把这个任务对应的标记从group移除
  29.        dispatch_group_leave(group);
  30.    });
  31.    
  32.    // 下载图片C
  33.    // 1.为图片C的下载操作,向group里面添加标记
  34.    dispatch_group_enter(group);
  35.    // 2.实现异步下载
  36.    dispatch_async(queue, ^{
  37.        NSLog(@"下载图片C...%@",[NSThread currentThread]);
  38.        
  39.        // 3.这个图片下载完成,说明任务结束,那么把这个任务对应的标记从group移除
  40.        dispatch_group_leave(group);
  41.    });
  42.    
  43.    // 异步监听 : 这个函数是在group里面的标记为空的时候,会自动调用
  44.    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  45.        
  46.        // 写图片下载完成之后的代码
  47.        NSLog(@"刷新UI %@",[NSThread currentThread]);
  48.    });
  49. }


0 0
原创粉丝点击