GCD 的使用

来源:互联网 发布:linux select c代码 编辑:程序博客网 时间:2024/05/16 07:06

GCD : 纯 C 语言的 API

GCD 核心
1.任务:执行什么操作
同步:永远只在当前线程从上往下,依次执行 执行,这个就叫做同步
异步:永远不在当前的线程上执行,它跑到别的线程上面去执行。
总结:同步方法 永远在当前线程上执行,所以没有开辟线程的能力。
异步方法,因为要在别的线程上去执行,所以它具有开辟线程的能力。
当遇到主队列,这个奇葩的时候,它就不起作用

2.队列:用来存放任务
作用:将相同的任务放在同一个队列中,方便管理

a.串行队列:
加入到里面的任务是一个一个有顺序的调度的。

    串行队列,同步任务        特点:有顺序的执行,并且不会开辟新线程,就在当前线程执行        应用场景:FMDB,它为什么要设计成串行队列,同步任务,为了保证数据的安全
/** *  串行队列,同步任务执行 */- (void)selrilSync {  // 1.创建任务  void (^task1)() = ^() {    NSLog(@"task1----%@", [NSThread currentThread]);  };  void (^task2)() = ^() {    NSLog(@"task2----%@", [NSThread currentThread]);  };  void (^task3)() = ^() {    NSLog(@"task3----%@", [NSThread currentThread]);  };  // 2.创建队列 串行队列  dispatch_queue_t serial =      dispatch_queue_create("cn.jingcheng", DISPATCH_QUEUE_SERIAL);  //将任务添加带队列中  dispatch_sync(serial, task1);  dispatch_sync(serial, task2);  dispatch_sync(serial, task3);}
    串行队列,异步任务        特点:有顺序的执行,并且在开辟的新的线程中执行,并且只开一条线程!!!        应用场景:耗时操作,并且有严格先后顺序        去付费网站上,下载片        登录--->付费--->下载
/** *  串行队列,异步执行 */- (void)serialAsync {  void (^task1)() = ^() {    NSLog(@"task1----%@", [NSThread currentThread]);  };  void (^task2)() = ^() {    NSLog(@"task2----%@", [NSThread currentThread]);  };  void (^task3)() = ^() {    NSLog(@"task3----%@", [NSThread currentThread]);  };  dispatch_queue_t serial = dispatch_queue_create("cn.jingcheng", NULL);  dispatch_async(serial, task1);  dispatch_async(serial, task2);  dispatch_async(serial, task3);}

b.并发队列:
特点:
任务可以同时执行,这样可以提高程序的运行效率.

    并发队列,同步任务        特点:没有开辟新线程,同时是按照顺序        应用场景:开发中几乎不用
/** *  并发队列,同步任务执行 */- (void)concurrentSync {  void (^task1)() = ^() {    NSLog(@"task1----%@", [NSThread currentThread]);  };  void (^task2)() = ^() {    NSLog(@"task2----%@", [NSThread currentThread]);  };  void (^task3)() = ^() {    NSLog(@"task3----%@", [NSThread currentThread]);  };  dispatch_queue_t concurrent =      dispatch_queue_create("cn.jingcheng", DISPATCH_QUEUE_CONCURRENT);  dispatch_sync(concurrent, task1);  dispatch_sync(concurrent, task2);  dispatch_sync(concurrent, task3);}
    并发队列,异步任务        特点:会开线程,开N条,表示不固定,因为我们的线程循环利用的功能       没有顺序.        应用场景:            比如下载多部片
/** *  并发队列,异步任务执行 */- (void)concurrentAsync {  void (^task1)() = ^() {    NSLog(@"task1----%@", [NSThread currentThread]);  };  void (^task2)() = ^() {    NSLog(@"task2----%@", [NSThread currentThread]);  };  void (^task3)() = ^() {    NSLog(@"task3----%@", [NSThread currentThread]);  };  dispatch_queue_t concurrent =      dispatch_queue_create("cn.jingcheng", DISPATCH_QUEUE_CONCURRENT);  dispatch_async(concurrent, task1);  dispatch_async(concurrent, task2);  dispatch_async(concurrent, task3);}

c.全局队列:
和并发队列,执行效果一样,只是说,并发队列,需要我们程序员,自己创建
而全局队列,是由于系统提供

    特点:        任务可以同时执行,这样可以提高程序的运行效率.     全局队列,同步任务     特点:没有开辟新线程,同时是按照顺序     应用场景:开发中几乎不用     全局队列,异步任务     特点:会开线程,开N条,表示不固定,因为我们的线程循环利用的功能       没有顺序.     应用场景:     比如下载多部片
/** *  全局队列 */- (void)globalQueue{    dispatch_queue_t global = dispatch_get_global_queue(0, 0);    //全局队列同步执行任务    dispatch_sync(global, ^{        NSLog(@"%@",[NSThread currentThread]);    });    //全局队列异步执行任务    dispatch_sync(global, ^{        NSLog(@"%@",[NSThread currentThread]);    });}

d.主队列(奇葩):
特点:
它永远在主线程工作,这个是苹果给开发人员,提供,回到主线程做事的一种机制

    主队列,同步任务        特点:主队列,只有在`主线程空闲`的时候,才能调度里面的任务        造成死锁    主队列,异步任务        应用场景:        回到主线程做事,一般是做和UI相关的工作.
/** *  主队列 */- (void)mainQueue {  dispatch_queue_t mainQ = dispatch_get_main_queue();  //全局队列同步执行任务 (死锁)  dispatch_sync(mainQ, ^{    NSLog(@"%@", [NSThread currentThread]);  });  //全局队列异步执行任务  dispatch_sync(mainQ, ^{    NSLog(@"%@", [NSThread currentThread]);  });}
    总结:任务的优先级比队列优先级高,所以我们在队列和任务的各种组合的时候,首先要看我们的任务.    1.开不开线程,由任务决定        异步才有开辟线程的能力,同步没有开辟线程的能力        异步是在其它线程上执行,同步,在当前线程上执行.        iOS 8.0 之后,GCD 能够开启非常多的线程        iOS 7.0 以及之前,GCD 通常只会开启 5~6 条线程    2.在开发中,主队列比较奇葩,主队列,就是苹果提供给我们,快速回到主线程的种实现机制.

开发中队列的选择
多线程的目的:将耗时的操作放在后台执行!

串行队列,只开一条线程,所有任务顺序执行

队列组
有这么1种需求
首先:分别异步执行2个耗时的操作
其次:等2个异步操作都执行完毕后,再回到主线程执行操作

如果想要快速高效地实现上述需求,可以考虑用队列组

  //创建队列组    dispatch_group_t group =  dispatch_group_create();    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        // 执行1个耗时的异步操作    });    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        // 执行1个耗时的异步操作    });    dispatch_group_notify(group, dispatch_get_main_queue(), ^{        // 等前面的异步操作都执行完毕后,回到主线程...    });
- (void)cacheStatusImage:(NSArray *)array and:(FinishedArray)finish {  if (array.count == 0) {    finish(nil, nil);    return;  }    //创建线程组  dispatch_group_t group = dispatch_group_create();  for (XFStatues *statues in array) {    NSArray *urls = statues.danLoadPicUrl;    if (urls.count != 1) {      continue;    }    for (NSURL *imageUrl in urls) {        //操作开始      dispatch_group_enter(group);      [[SDWebImageManager sharedManager] downloadImageWithURL:imageUrl          options:0          progress:^(NSInteger receivedSize, NSInteger expectedSize) {          }          completed:^(UIImage *image, NSError *error,                      SDImageCacheType cacheType, BOOL finished,                      NSURL *imageURL) {            NSLog(@"单张图片下载完成");              //操作结束            dispatch_group_leave(group);          }];    }  }  //线程组下载图片任务全部完成,主线程完成所有图片下载回调  dispatch_group_notify(group, dispatch_get_main_queue(), ^{    NSLog(@"所有图片下载完成");    finish(nil, array);  });}

如果任务有先后执行顺序的要求
效率低 -> 执行慢 -> “省电”
有的时候,用户其实不希望太快!例如使用 3G 流量,”省钱”

并发队列,会开启多条线程,所有任务不按照顺序执行
如果任务没有先后执行顺序的要求
效率高 -> 执行快 -> “费电”
WIFI,包月

实际开发过程中开辟线程数
WIFI 线程数 6 条
3G / 4G 移动开发的时候,2~3条,再多会费电费钱!

0 0
原创粉丝点击