zoukankan      html  css  js  c++  java
  • iOS多线程_04_GCD

    一、基本概念

    1、什么是GCD

    • 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”
    • 纯C语言,提供了非常多强大的函数

    2、GCD的优势

    • GCD是苹果公司为多核的并行运算提出的解决方案
    • GCD会自动利用更多的CPU内核(比如双核、四核)
    • GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
    • 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

    3、任务和队列

    (1)GCD中有2个核心概念

      任务:执行什么操作

      队列:用来存放任务

    (2)GCD的使用就2个步骤

      <1>定制任务:确定想做的事情

      <2>将任务添加到队列中:

      GCD会自动将队列中的任务取出,放到对应的线程中执行

      任务的取出遵循队列的FIFO原则:先进先出,后进后出

    二、执行任务

    1、执行任务

    (1)GCD中有2个用来执行任务的函数

      用同步的方式执行任务

      dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

      queue:队列

      block:任务

      用异步的方式执行任务

      dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

    (2)同步和异步的区别

      同步:在当前线程中执行

      异步:在另一条线程中执行

    2、队列的类型

      GCD的队列可以分为2大类型

    (1)并行队列(Concurrent Dispatch Queue)

      可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)

      并发功能只有在异步(dispatch_async)函数下才有效

    (2)串行队列(Serial Dispatch Queue)

      让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

    3、比较容易混淆的术语:同步、异步、并发、串行

    (1)同步和异步决定了要不要开启新的线程

      同步:在当前线程中执行任务,不具备开启新线程的能力

      异步:在新的线程中执行任务,具备开启新线程的能力

    (2)并发和串行决定了任务的执行方式

      并发:多个任务并发(同时)执行

      串行:一个任务执行完毕后,再执行下一个任务

    三、“串行队列”、“并行队列”、“全局队列”和“主队列

      DISPATCH_QUEUE_SERIAL   串行队列 与NULL等效

      DISPATCH_QUEUE_CONCURRENT 并行队列

    1、串行队列

    (1)第一种:串行队列,异步任务

     1     // 1.串行队列
     2     // 在使用GCD的时候,先敲dispatch
     3     // 在C语言中,定义对象通常是以 _t 或者 Ref 结尾的
     4     // dispatch_queue_t q = dispatch_queue_create("ios", DISPATCH_QUEUE_SERIAL);
     5     dispatch_queue_t q = dispatch_queue_create("ios", NULL);
     6     
     7     NSLog(@"%@", [NSThread currentThread]);
     8     
     9     // 2. 异步任务 async,能够开线程
    10     // 串行队列中,异步任务最多只能开一条线程,所有任务顺序执行!
    11     // 串行队列,异步任务,在多线程中,是斯坦福大学最推荐的一种多线程方式!
    12     // 优点:将任务放在其他线程中工作,每个任务顺序执行,便于调试
    13     // 缺点:并发能力不强,最多只能使用一条子线程!
    14     for (int i = 0; i < 10; i++) {
    15         dispatch_async(q, ^{
    16             NSLog(@"%@ - %d", [NSThread currentThread], i);
    17         });
    18     }
      ios是队列的名称,它的作用是在调试的时候,可以看到在某个线程上执行的是哪个队列的任务。
     
     

      输出结果:

      结果说明:

      ① 异步任务 async 能够开线程

      ② 串行队列中,异步任务最多只能开一条线程,所有任务顺序执行!

      ③ 串行队列,异步任务,在多线程中,是斯坦福大学最推荐的一种多线程方式!

      优点:将任务放在其它线程中工作,每个任务顺序执行,便于调试

      缺点:并发能力不强,最多只能使用一条子线程!

    (2)第二种:串行队列,同步任务

    1     // 2. 同步任务 sync(没用处)
    2     for (int i = 0; i < 10; i++) {
    3         dispatch_sync(q, ^{
    4             NSLog(@"%@ - %d", [NSThread currentThread], i);
    5         });
    6     }

      输出结果:

      从输出结果可以看出,串行队列,同步任务,是在主线程顺序执行的,默认就是顺序执行的,所以这个没什么用。

    2、并行队列

    (1)第一种:并行队列,异步任务

     1     // 1.并行队列
     2     dispatch_queue_t q = dispatch_queue_create("ios", DISPATCH_QUEUE_CONCURRENT);
     3     
     4     NSLog(@"%@", [NSThread currentThread]);
     5     
     6     // 2.异步任务
     7     for (int i = 0; i < 10; i++) {
     8         dispatch_async(q, ^{
     9             NSLog(@"%@ - %d", [NSThread currentThread], i);
    10         });
    11     }

      输出结果是:

      ① 并行队列,异步任务,开启了多条子线程执行。

      ② 异步任务,会在多条线程上工作,具体开多少条线程,由系统决定

      ③ 仍然是按照任务添加到队列中的顺序被调度,只是执行先后可能会有差异!

      ④ 能够将耗时的操作,放到子线程中工作

      ⑤ 与串行队列异步任务相比,并发性能更好!但是执行的先后顺序,不固定

    (2)第二种,并行队列,同步任务

     1 // 1.并行队列
     2         dispatch_queue_t q = dispatch_queue_create("ios", DISPATCH_QUEUE_CONCURRENT);
     3         
     4         NSLog(@"%@", [NSThread currentThread]);
     5         
     6         // 2.同步任务
     7         for (int i = 0; i < 10; i++) {
     8             dispatch_sync(q, ^{
     9                 NSLog(@"%@ - %d", [NSThread currentThread], i);
    10             });
    11         }

    输出结果:

    跟串行队列,同步任务的输出结果是相同的。

    3、全局队列

      全局队列又叫全局并行队列全局并发队列,所以全局队列是并行队列

     1     // 1. 获取全局队列(与自定义并行队列的区别就是名字显示,其他都一样)
     2     dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     3     // 使用全局队列,不需要考虑共享的问题
     4     
     5     // 3. 同步任务
     6     for (int i = 0; i < 10; i++) {
     7         dispatch_sync(q, ^{
     8             NSLog(@"%@ - %d", [NSThread currentThread], i);
     9         });
    10     }
    11     
    12     // 2. 异步任务
    13     for (int i = 0; i < 10; i++) {
    14         dispatch_async(q, ^{
    15             NSLog(@"%@ - %d", [NSThread currentThread], i);
    16         });
    17     }

      因为是 DISPATCH_QUEUE_PRIORITY_DEFAULT(默认的优先级)输出结果跟在自定义并行队列里的结果一样

      全局队列使用更普遍一些,因为使用起来简单

      不需要考虑共享问题:指MRC中,自定义并行队列 dispatch_queue_t q = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);需要自己释放队列dispatch_release(q);

      因此,无论是ARC还是MRC,使用默认优先级的全局队列不用考虑共享问题。

      唯一跟自定义并行队列的区别是,队列名字不同

      

    4、主队列

      是专门在主线程上工作的队列,即专门调度任务在主队列上执行

    (1)主队列,异步任务

    1     // 1. 获取主队列
    2     dispatch_queue_t q = dispatch_get_main_queue();
    3     
    4     // 2. 异步任务,在主线程上依次顺序执行
    5     for (int i = 0; i < 10; i++) {
    6         dispatch_async(q, ^{
    7             NSLog(@"%@ - %d", [NSThread currentThread], i);
    8         });
    9     }

      输出结果:

      输出结果说明,主队列上异步任务依次顺序执行,跟串行队列的异步任务不同的是,没有开启子线程。

      所以,异步任务是以异步的方式执行,不一定在哪个线程上。有可能在主线程上,也有可能在子线程上。

    (2)主队列,同步任务(千万不能使用

    1     // 1. 获取主队列
    2     dispatch_queue_t q = dispatch_get_main_queue();
    3     
    4     // 3. 不要同步任务(死锁!!!)
    5     dispatch_sync(q, ^{
    6         NSLog(@"不会输出任何东西");
    7     });

      不会输出任何东西,没有任何反应,这种情况叫任务死锁

      因为,应用程序已启动,就会建立一个线程,这个线程被称为主线程。而主队列的同步任务会一直等待主线程执行完了,只有程序挂了,主线程才结束,根本就不会执行主队列的同步任务。

  • 相关阅读:
    从有序的数组中查找某个值
    OJ 21658::Monthly Expense(二分搜索+最小化最大值)
    OJ 21651::Cow Hurdles(佛罗一德的变式)
    Oj 24260: Lilypad Pond (神奇广搜题,状态搜索)
    MongoDB常用语句
    MongoDB可视化工具之mongoBooster
    MongoDB的安装,mongod和mongo的区别
    数组遍历及其他方法
    MongoDB的安装与卸载与再安装
    MongoDB下载安装步骤+文件解析
  • 原文地址:https://www.cnblogs.com/yudigege/p/3931671.html
Copyright © 2011-2022 走看看