21、GCD

作者: ChenL | 来源:发表于2020-12-09 10:04 被阅读0次
GCD的优势:
  • GCD 是苹果公司为多核的并行运算 提出的 解决方案
  • GCD会 自动利用 更多的cpu内核 (如:双核、四核)
  • GCD会 自动管理 线程的 生命周期(创建线程、调度任务、销毁线程)
  • 程序员 只需要 告诉GCD 想要执行什么任务,不需要编写任何线程管理代码

重点
将任务添加到队列,并指定任务执行的函数

GCD的核心

GCD的核心 主要是由任务 + 队列 + 函数 构成

日常开发中,GCD一般写成下面的形式:

 dispatch_async( dispatch_queue_create("com.xxx.Queue", NULL), ^{
   NSLog(@"GCD基本使用");
});

拆分如下:

//********GCD基础写法********
//创建任务
dispatch_block_t block = ^{
    NSLog(@"hello GCD");
};

//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.xxx.Queue", NULL);

//将任务添加到队列,并指定函数执行
dispatch_async(queue, block);
  • 使用 dispatch_block_t 创建任务 (执行操作的意思,任务使用block封装,任务的block 没有参数 也 没有返回值)
  • 使用 dispatch_queue_t 创建队列
  • 将任务添加到队列,并指定执行任务的函数 dispatch_async
函数与 队列

一、函数:

在GCD 中 执行任务的方式 有两种,同步执行异步执行,分别对应 函数dispatch_sync 和 异步函数 dispatch_async

1、 同步执行,对应函数 dispatch_sync

  • 必须等待当前语句执行完毕,才会执行下一条语句
  • 不会开启线程,即 不具备开启新线程的能力
  • 在当前线程中执行block任务
    2、异步执行,对应异步函数 dispatch_async
  • 不用等待当前语句执行完毕,就可以执行下一条语句
  • 会开启线程 block任务,即具备开启线程的能力(但并不一定开启新线程,这个与任务所指定的队列类型有关)
  • 异步 是 多线程 的代名词

综上,两种执行方式的区别:

  • 是否 等待 队列的任务执行完毕
  • 是否具备开启新线程的能力

一、队列:

串行队列 && 并行队列

多线程中所说的 队列 是指 执行任务的等待队列,即用来存放任务的队列。队列 是一种特殊的 线性表,遵循 先进先出(FIFO)原则,即新任务总是被 插入到对尾,而任务的读取 从队首开始读取。每读取一个任务,则队列中释放一个任务。

image.png

在GCD 中,队列主要分为串行队列 和 并行队列


image.png

1、串行队列 :

每次 只有一个任务被执行,等待上一个任务执行完毕再执行下一个,即 只开启一个线程(同一时刻只调度一个任务执行)

  • 使用dispatch_queue_create("xxx", DISPATCH_QUEUE_SERIAL);创建串行队列

  • 其中 DISPATCH_QUEUE_SERIAL 也可以使用NULL 表示,者两者均表示 默认的串行队列

// 串行队列的获取方法
dispatch_queue_t serialQueue1 = dispatch_queue_create("com.xxx.Queue", NULL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("com.xxx.Queue", DISPATCH_QUEUE_SERIAL);

2、并行队列:

一次可以并发执行多个任务,即 开启多线程,并同时执行多个任务(同一时刻可以调度多个任务执行)

  • 使用 dispatch_queue_create("xxx", DISPATCH_QUEUE_CONCURRENT); 创建并发队列

  • 注意:并发队列的并发功能只有在异步函数下才有效

// 并发队列的获取方法
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.xxx.Queue", DISPATCH_QUEUE_CONCURRENT);

3、主队列:

GCD中提供的特殊的串行队列

  • 专门用来 在主线程上调度任务的串行队列,依赖于主线程、主runloop,在main函数调用之前 自动创建.

  • 不会开启线程

  • 如果当前主线程正在有任务执行,那么无论主队列中当前被添加了什么任务,都不会被调度

  • 使用dispatch_get_main_queue() 获得主队列

  • 通常用于 返回主线程 更新UI 使用

//主队列的获取方法
dispatch_queue_t mainQueue = dispatch_get_main_queue();

4、全局并发队列:

GCD提供的默认的并发队列

  • 为了方便程序员的使用,苹果提供了全局队列

  • 在使用多线程开发时,如果对队列没有特殊要求,在执行异步任务时,可以直接使用全局队列

  • 使用 dispatch_get_global_queue 获取全局并发队列,最简单的写法:dispatch_get_global_queue(0, 0)

第一个参数:队列优先级,默认优先级为DISPATCH_QUEUE_PRIORITY_DEFAULT=0,在ios9 之后,已经被服务质量(quality-of-service) 取代

第二个参数:0

//全局并发队列的获取方法
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);

//优先级从高到低(对应的服务质量)依次为

  • DISPATCH_QUEUE_PRIORITY_HIGH -- QOS_CLASS_USER_INITIATED
  • DISPATCH_QUEUE_PRIORITY_DEFAULT -- QOS_CLASS_DEFAULT
  • DISPATCH_QUEUE_PRIORITY_LOW -- QOS_CLASS_UTILITY
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND -- QOS_CLASS_BACKGROUND

日常开发中,全局队列+并发队列,一般是这样配合使用的:

//主队列 + 全局并发队列的日常使用
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //执行耗时操作
        dispatch_async(dispatch_get_main_queue(), ^{
            //回到主线程进行UI操作
        });
    });
函数与 队列的不同组合

1、 串行队列+同步函数

任务:按顺序执行,任务一个接一个的在当前线程执行,不会开辟新线程。

2、串行队列+异步函数

任务:按顺序执行,任务一个接一个的执行,会开辟新线程

3、并发队列+同步函数

任务:按顺序执行,任务一个接一个的执行,不开辟新新线程

4、并发队列+异步函数

任务:乱序执行,任务执行无顺序,会开辟新线程

5、主队列+同步函数

造成死锁,任务 :互相等待,造成死锁

.png

造成死锁的原因分析如下:

  • 主队列有两个任务:顺序为:NSLog任务 -> 同步block

  • 执行NSLog任务后,执行同步Block ,会将任务1(即i=1时)加入到主队列,主队列顺序为:NSLog任务 - >同步block - >任务1

  • 任务1 的执行需要 等待同步block执行完毕 才会执行,而 同步block 的执行需要 等待 任务1执行完毕,所以就造成了 任务相互等待 的情况,即造成 死锁崩溃

死锁现象

  • 主线程 因为你 同步函数的原因 等着先执行任务
  • 主队列等着主线程的任务 执行完毕再执行自己的任务
  • 主队列 和 主线程相互等待 会造成死锁

6、主队列+异步函数

任务 按顺序执行,任务一个接一个的执行,不开辟线程

7、全局并发队列+ 同步函数

按顺序执行,任务一个接一个的执行,不开辟新线程

8、 全局并发队列+异步函数

任务 乱序执行,会开辟新线程

相关文章

  • 21、GCD

    GCD的优势: GCD 是苹果公司为多核的并行运算 提出的 解决方案 GCD会 自动利用 更多的cpu内核 (如:...

  • 多线程之GCD

    GCD介绍 1、GCD简介 2、GCD任务和队列 3、GCD 的基本使用 4、GCD 线程间的通信 5、GCD 的...

  • 扩展GCD(求逆元,解同余方程等等)

    首先要知道gcd函数的基本性质:gcd(a,b)=gcd(b,a)=gcd(|a|,|b|)=gcd(b,a%b)...

  • iOS - GCD

    目录 GCD简介 GCD核心概念 GCD队列的使用 GCD的常见面试题 GCD简介 Grand Central D...

  • iOS-多线程:GCD

    GCD 简介 GCD 任务和队列 GCD 的使用步骤 GCD 的基本使用(6种不同组合区别) GCD 线程间的通信...

  • 浅析GCD

    GCD目录: 1. GCD简介 为什么要用GCD呢? GCD可用于多核的并行运算GCD会自动利用更多的CPU内核(...

  • 7.3 多线程-GCD

    多线程-GCD 多线程-GCD-串行并行 多线程-GCD.png GCD-线程的通讯、延时操作、定时器 GCD-线...

  • iOS 多线程--GCD

    一、GCD基本介绍 1.GCD简介 GCD是Grand Central Dispatch的缩写,GCD是苹果推出的...

  • 自用算法模板(JAVA版)

    一、数论 1)GCD GCD(求最大公约数) QGCD(快速GCD) extGCD(拓展GCD,解决ax + by...

  • GCD介绍

    一、GCD简单介绍 什么是GCD GCD优势 任务和队列 GCD有2个核心概念 GCD的使用就2个步骤 将任务添加...

网友评论

      本文标题:21、GCD

      本文链接:https://www.haomeiwen.com/subject/bpjaiktx.html