• GCD中有2个核心概念

    • 任务:执行什么操作
    • 队列:用来存放任务
  • 执行任务

    • 同步方法: dispatch_sync

      dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
      queue:队列
      block:任务
    • 异步方法: dispatch_async
      dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
    • 同步和异步的区别
      • 同步:只能在当前线程中执行任务,不具备开启新线程的能力
      • 异步:可以在新的线程中执行任务,具备开启新线程的能力
  • 队列

    • 并发队列

      • 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
      • 并发功能只有在异步(dispatch_async)函数下才有效
    • 串行队列
      • 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
  • 注意点

    • 同步和异步主要影响:能不能开启新的线程

      • 同步:只是在当前线程中执行任务,不具备开启新线程的能力
      • 异步:可以在新的线程中执行任务,具备开启新线程的能力
    • 并发和串行主要影响:任务的执行方式
      • 并发:允许多个任务并发(同时)执行
      • 串行:一个任务执行完毕后,再执行下一个任务
  • 各种任务队列搭配

    • 同步 + 串行
    • /*
      同步 + 串行: 不会开启新的线程
      注意点: 如果是调用 同步函数, 那么会等同步函数中的任务执行完毕, 才会执行后面的代码
      */
      - (void)syncSerial
      {
      // 1.创建一个串行队列
      // #define DISPATCH_QUEUE_SERIAL NULL
      // 所以可以直接传NULL
      dispatch_queue_t queue = dispatch_queue_create("com.520it.lnj", NULL); // 2.将任务添加到队列中
      dispatch_sync(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      }); NSLog(@"---------");
      }
    • 同步 + 并发 *
      /*
      同步 + 并发 : 不会开启新的线程
      妻管严
      */
      - (void)syncConCurrent
      {
      // 1.创建一个并发队列
      dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 2.将任务添加到队列中
      dispatch_sync(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      }); NSLog(@"---------");
      }
    • 异步 + 串行 *
      /*
      异步 + 串行:会开启新的线程
      但是只会开启一个新的线程
      注意: 如果调用 异步函数, 那么不用等到函数中的任务执行完毕, 就会执行后面的代码
      */
      - (void)asynSerial
      {
      // 1.创建串行队列
      dispatch_queue_t queue = dispatch_queue_create("com.520it.lnj", DISPATCH_QUEUE_SERIAL);
      /*
      能够创建新线程的原因:
      我们是使用"异步"函数调用
      只创建1个子线程的原因:
      我们的队列是串行队列
      */
      // 2.将任务添加到队列中
      dispatch_async(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      }); NSLog(@"--------");
      }
    • 异步 + 并发 *
      /*
      异步 + 并发 : 会开启新的线程
      如果任务比较多, 那么就会开启多个线程
      */
      - (void)asynConcurrent
      {
      /*
      执行任务
      dispatch_async
      dispatch_sync
      */ /*
      第一个参数: 队列的名称
      第二个参数: 告诉系统需要创建一个并发队列还是串行队列
      DISPATCH_QUEUE_SERIAL :串行
      DISPATCH_QUEUE_CONCURRENT 并发
      */
      // dispatch_queue_t queue = dispatch_queue_create("com.520it.lnj", DISPATCH_QUEUE_CONCURRENT); // 系统内部已经给我们提供好了一个现成的并发队列
      /*
      第一个参数: iOS8以前是优先级, iOS8以后是服务质量
      iOS8以前
      * - DISPATCH_QUEUE_PRIORITY_HIGH 高优先级 2
      * - DISPATCH_QUEUE_PRIORITY_DEFAULT: 默认的优先级 0
      * - DISPATCH_QUEUE_PRIORITY_LOW: 低优先级 -2
      * - DISPATCH_QUEUE_PRIORITY_BACKGROUND: iOS8以后
      * - QOS_CLASS_USER_INTERACTIVE 0x21 用户交互(用户迫切想执行任务)
      * - QOS_CLASS_USER_INITIATED 0x19 用户需要
      * - QOS_CLASS_DEFAULT 0x15 默认
      * - QOS_CLASS_UTILITY 0x11 工具(低优先级, 苹果推荐将耗时操作放到这种类型的队列中)
      * - QOS_CLASS_BACKGROUND 0x09 后台
      * - QOS_CLASS_UNSPECIFIED 0x00 没有设置 第二个参数: 废物
      */
      dispatch_queue_t queue = dispatch_get_global_queue(0, 0); /*
      第一个参数: 用于存放任务的队列
      第二个参数: 任务(block) GCD从队列中取出任务, 遵循FIFO原则 , 先进先出
      输出的结果和苹果所说的原则不符合的原因: CPU可能会先调度其它的线程 能够创建新线程的原因:
      我们是使用"异步"函数调用
      能够创建多个子线程的原因:
      我们的队列是并发队列
      */
      dispatch_async(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      });
      }
    • 异步 + 主队列 *
       异步 + 主队列 : 不会创建新的线程, 并且任务是在主线程中执行
      */
      - (void)asyncMain
      {
      // 主队列:
      // 特点: 只要将任务添加到主队列中, 那么任务"一定"会在主线程中执行 \
      无论你是调用同步函数还是异步函数
      dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{
      NSLog(@"%@", [NSThread currentThread]);
      });
      }
    • 同步 + 主队列 *
      /*
      如果是在主线程中调用同步函数 + 主队列, 那么会导致死锁
      导致死锁的原因:
      sync函数是在主线程中执行的, 并且会等待block执行完毕. 先调用
      block是添加到主队列的, 也需要在主线程中执行. 后调用
      */
      - (void)syncMain
      {
      NSLog(@"%@", [NSThread currentThread]);
      // 主队列:
      dispatch_queue_t queue = dispatch_get_main_queue(); // 如果是调用 同步函数, 那么会等同步函数中的任务执行完毕, 才会执行后面的代码
      // 注意: 如果dispatch_sync方法是在主线程中调用的, 并且传入的队列是主队列, 那么会导致死锁
      dispatch_sync(queue, ^{
      NSLog(@"----------");
      NSLog(@"%@", [NSThread currentThread]);
      });
      NSLog(@"----------");
      }
  • GCD线程间通信

dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});
});
  • GCD其它用法
  • 延时执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后执行这里的代码...
});
  • 一次性代码

    • 使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次
    •  static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ 
      
      // 只执行1次的代码(这里面默认是线程安全的) 
      
      });

- 快速迭代

dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
// 执行10次代码,index顺序不确定
});
  • barrier (栅栏)

    • 在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
    • 不能是全局的并发队列
    • 所有的任务都必须在一个队列中
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
  • 队列组
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(), ^{
// 等前面的异步操作都执行完毕后,回到主线程...
});

多线程 -- GCD的更多相关文章

  1. iOS 多线程GCD的基本使用

    <iOS多线程简介>中提到:GCD中有2个核心概念:1.任务(执行什么操作)2.队列(用来存放任务) 那么多线程GCD的基本使用有哪些呢? 可以分以下多种情况: 1.异步函数 + 并发队列 ...

  2. iOS多线程 GCD

    iOS多线程 GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法. dispatch queue分成以下三种: 1)运行在主线程的Main que ...

  3. 修改版: 小伙,多线程(GCD)看我就够了,骗你没好处!

    多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系 ...

  4. ios多线程-GCD基本用法

    ios中多线程有三种,NSTread, NSOperation,GCD 这篇就讲讲GCD的基本用法 平时比较多使用和看到的是: dispatch_async(dispatch_get_global_q ...

  5. iOS 多线程GCD简介

    一.简介 1.1 GCD (Grand Central Dispatch )是Apple开发的一个多核编程的解决方法. Grand 含义是“伟大的.宏大的”,Central含义“中央的”,Dispat ...

  6. 多线程GCD的基本使用以及注意点

    GCD的使用  一:队列    1.串行队列:添加到队列中的任务是一个一个执行的    2.并行(发)队列:添加到队列中的任务是多个同时执行的(一个队列中的多个任务可以同时执行)    3.主队列:里 ...

  7. IOS开发之多线程 -- GCD的方方面面

    前言:这篇GCD的博文是本人阅读了很多海内外大神的关于GCD的文章,以及结合之前自己对GCD的粗浅的认识,然后取其精华,去其槽粕,综合起来的笔记,而且是尽可能的以通熟易懂的并且是正确的理论论述方式呈现 ...

  8. 刀哥多线程GCD核心概念gcd

    GCD GCD 核心概念 将任务添加到队列,并且指定执行任务的函数 任务使用 block 封装 任务的 block 没有参数也没有返回值 执行任务的函数 异步 dispatch_async 不用等待当 ...

  9. ios开发多线程--GCD

    引言 虽然GCD使用很广,而且在面试时也经常问与GCD相关的问题,但是我相信深入理解关于GCD知识的人肯定不多,大部分都是人云亦云,只是使用过GCD完成一些很简单的功能.当然,使用GCD完成一些简单的 ...

  10. 多线程GCD

    经常使用:规避很多线程相关的复杂的逻辑 为什么会gcd?因为pthread和nsthread要求开发人员对线程相关的知识了解深入; 手动启动线程:加锁/解锁;造成很多隐患 --> 苹果公司给出了 ...

随机推荐

  1. linux 下 jdk tar.gz 包安装方法

    JDK安装 tar.gz为解压后就可使用的版本,这里我们将jdk-7u3-linux-i586.tar.gz解压到/usr/local/下. 1.解压 解压到当前目录:$ tar -zxvf /opt ...

  2. 比较合并工具vimdiff的主要用法归纳

    参考:https://www.ibm.com/developerworks/cn/linux/l-vimdiff/ vimdiff主要用法归纳如下:   1.打开文件 vimdiff file1 fi ...

  3. Windows下WEB服务器的选择与搭建

    本文主要基于支持perl的web服务器的选择. 一直基于web开发,服务器都是linux下使用webmin搭建的,惭愧的说一句,这么多年,也好好研究过WEB服务器,单从这个角度,是不是可以反应出web ...

  4. 使用css实现全兼容tooltip提示框

    在上一篇文章中,使用css实现了一个全兼容的三角形图标,这个三角型图标可以使用于多种场景,比如下拉图标.多级菜单等,这篇文章我们使用这个图标通过纯css来实现一个我们常见的tooltip提示框. 最终 ...

  5. POJ C程序设计进阶 编程题#1:含k个3的数

    编程题#1:含k个3的数 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 输 ...

  6. 线程池(C#)

    转自:http://blog.sina.com.cn/s/blog_494305f30100ryw7.html 在这里你可以学到Microsoft研究CLR实现线程池的原理机制,从而更灵活的处理CLR ...

  7. 小菜的系统框架界面设计-灰姑娘到白雪公主的蜕变(工具条OutLookBar)

    灰姑娘本身也有自已的优点,但是却可能因为外貌不讨人喜欢,要变成白雪公主却需要有很多勇气和决心去改变自已: 有一颗善良的心 讨人喜爱的外貌   --蜕变-->  我这里讲的是一个工具条的蜕变过程, ...

  8. LevelDB系列之Log文件

    上节内容讲到log文件在LevelDb中的主要作用是系统故障恢复时,能够保证不会丢失数据.因为在将记录写入内存的Memtable之前,会先写入Log文件,这样即使系统发生故障,Memtable中的数据 ...

  9. php中empty(), is_null(), isset()函数区别

    empty(), is_null(), isset()真值表(区别) 我们先来看看这3个函数的功能描述 www.111cn.net isset 判断变量是否已存在,如果变量存在则返回 TRUE,否则返 ...

  10. 17.python自定义函数

    什么是函数,函数说白了就是将一系列代码封装起来,实现代码的重用. 什么是代码重用? 假设我有这样的需求: 但是我还是觉得太麻烦了,每次想吃饭的时候都要重复这样的步骤.此时,我希望有这样的机器: