GCD 的使用

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值