当前位置: 首页 > news >正文

iOS GCD的基本使用

一:什么是GCD

GCD的全程是:Grand Central Dispatch, 直白的用汉语翻译就是:厉害的中枢调度器.

GCD 是iOS 的多线程技术的实现方案,但是它并不是多线程技术,它是“并发解决技术”,是苹果公司研发的,会自动管理线程(这一段定义有点拗口,简单了解就行)

GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

二:CGD的两个核心概念

1.任务: 执行了什么操作(任务使用block来定义)

2.对列:(是一种数据结构,先进先出)用来存放任务

简而言之,就是 创建任务--创建对列-->把任务放到对列里.

执行任务有两种方式:同步执行(sync)和异步执行(async)

对列有两种类型:串行对列,并行对列

(代码里还有主队列:主队列 dispatch_get_main_queue(),但是它是一种特殊的串行对列)

(还有全局并发对列 dispatch_get_global_queue(),它也是一种并行对列)​​​​​​​

(注意:并行对列并不是说有多个对列并行,不管串行对列还是并行对列,都只有一个对列,对列里放的任务是串行的,叫串行对列,对列里放的任务是并行的,叫并行对列)

队列是一种特殊的线性表,采用 FIFO(先进先出)的原则.放入队列的里任务,先放先执行(按照代码从上到下运行的思想就是,哪个任务先写哪个任务先执行),

注意⚠️:这个“先进先出”的“出”,不是“出结果”的出,而是先“拿出来”执行的出.所以先放进去的任务先执行,但是并不一定先出结果,例如依次放入并行队列的异步任务A和异步任务B,先执行异步任务A,再执行任务B,但是A的逻辑比较耗时,B的结果出来了,A的结果还没出来.

所以理论上任务和对列有4种组合方案:

1.串行对列里添加同步任务;

2.串行对列里添加异步任务;

3.并行对列里添加同步任务; (并行对列里具备了多个任务一起执行的能力,但是由于加入的任务是同步的,所以无法多个任务一同执行,得排队执行)

4.并行对列里添加异步任务.

另外还有一个主对列 dispatch_get_main_queue()

主对列里添加了同步任务

主队列里添加了异步任务

几种组合的区别如下图:

以上图片可以总结为:

同步任务+并发对列:按顺序执行任务,不会开启新线程

异步任务+并发对列:不一定按顺序执行任务,会开启新线程(有几个任务就开启几个线程)

同步任务+串行对列:按顺序执行任务,不会开启新线程

异步任务+串行对列:按顺序执行任务,会开启一个新线程(不管有多少个任务,只有开一个新线程)

记忆点:只要是同步任务,都不会开启新线程;

             异步任务会开启新线程,N个异步任务放入到串行对列,只开一个线程,N个异步任务放入并         行对列,会开N个新线程

1.同步任务+并行对列:

//1.同步任务+并行对列
- (void)dispathDemo1
{dispatch_queue_t queue = dispatch_queue_create(@"同步任务+并行对列", DISPATCH_QUEUE_CONCURRENT);//在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务。NSLog(@"同步任务开始,当前线程==%@",[NSThread currentThread]);[NSThread sleepForTimeInterval:2]; // 模拟耗时操作//for循环,创建5个任务,放入queue种for (int i = 0; i < 5; i ++){//同步函数dispatch_sync(queue, ^{if (i == 1) {[NSThread sleepForTimeInterval:10];}NSLog(@"当前打印值==%d,线程==%@",i,[NSThread currentThread]);});}NSLog(@"同步任务结束,当前线程==%@",[NSThread currentThread]);
}

输出的顺序为:

同步任务开始,当前线程==<_NSMainThread: 0x600001704000>{number = 1, name = main}
当前打印值==0,线程==<_NSMainThread: 0x600001704000>{number = 1, name = main}
当前打印值==1,线程==<_NSMainThread: 0x600001704000>{number = 1, name = main}
当前打印值==2,线程==<_NSMainThread: 0x600001704000>{number = 1, name = main}
当前打印值==3,线程==<_NSMainThread: 0x600001704000>{number = 1, name = main}
当前打印值==4,线程==<_NSMainThread: 0x600001704000>{number = 1, name = main}
同步任务结束,当前线程==<_NSMainThread: 0x600001704000>{number = 1, name = main}

可以看到:

所有任务都是在当前线程(主线程)中执行的,没有开启新的线程(同步执行不具备开启新线程的能力)
所有任务都在打印的 同步任务开始和syncConcurrent begin—syncConcurrent end之间执行的(同步任务需要等待队列的任务执行结束)
任务按顺序执行的。按顺序执行的原因:虽然并发队列可以开启多个线程,并且同时执行多个任务。但是因为本身不能创建新线程,只有当前线程这一个线程(同步任务不具备开启新线程的能力),所以也就不存在并发。而且当前线程只有等待当前队列中正在执行的任务执行完毕之后,才能继续接着执行下面的操作(同步任务需要等待队列的任务执行结束)。所以任务只能一个接一个按顺序执行,不能同时被执行。

写累了,不想写了,具体可以参考文章:iOS 多线程GCD_gcd多线程-CSDN博客

https://blog.csdn.net/fengyuyxz/article/details/114835909?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogOpenSearchComplete%7ERate-2-114835909-blog-138373634.235%5Ev43%5Epc_blog_bottom_relevance_base1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogOpenSearchComplete%7ERate-2-114835909-blog-138373634.235%5Ev43%5Epc_blog_bottom_relevance_base1&utm_relevant_index=3​​​​​​​

三:CGD执行顺序

例1:

答案在下面代码块里:

- (void)GCDDemo1
{//并行对列dispatch_queue_t queue = dispatch_queue_create(@"并行对列", DISPATCH_QUEUE_CONCURRENT);NSLog(@"11111");dispatch_async(queue, ^{NSLog(@"2222");dispatch_async(queue, ^{NSLog(@"33333");});NSLog(@"4444");});NSLog(@"5555");/*打印顺序为1、5、2、4、31.1先打印,没问题2.代码运行到 第一个 dispatch_async 异步任务,由于异步任务耗时,且是并行队列,不影响下面的代码(不属于任务里的代码)运行,所以先打印53.进入异步任务dispatch_async,打印24.代码运行到第二个 dispatch_async 异步任务,原因与步骤2一样,先打印45.最后打印异步任务里的3*/
}

例2:

- (void)GCDDemo4
{dispatch_queue_t queue = dispatch_queue_create(@"并发对列", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{ //异步,耗时NSLog(@"11111");});dispatch_async(queue, ^{NSLog(@"2222");});dispatch_sync(queue, ^{NSLog(@"33333");});NSLog(@"00000");dispatch_async(queue, ^{NSLog(@"77777");});dispatch_async(queue, ^{NSLog(@"88888");});dispatch_async(queue, ^{NSLog(@"99999");});/*A:1230789B:1237890C:3120789D:2137890答案为A或C解答:1.1和2同为异步函数,谁先谁后执行完毕不好说,得看函数本身的耗时情况,所以顺序1、2或者2、1都行2.同理 789 也是没有三个之间也是没有顺序的,789、879、978等等都行3.关键点在于 同步函数3,同步函数没走完之前,它后面的函数是不会走的,所以3一定在0的前面.3.1.同步函数3卡住的是第36行代码,因为是并行对列,结合步骤1,可以得出123执行的顺序也是不一定的,谁的函数耗时少,谁先执行.4.得出结论-->123 在 0 的面前.5.123 执行完毕之后 一定是先执行0,因为789都是异步耗时操作6.所以得出结论123随便排列,然后到0,再到789随便排列.7.满足以上要求的只有A和C8.这道题是选择题,如果是填空题,还有好多种可能,例如:2130978、2130897等等(可能是因为答案有多种,才出的选择题)*/}

例3:

例子3来看一下不同队列和不同任务的区别:

3.1.并行队列/串行队列 + 同步任务, 执行顺序都是123. 由此可以得出结论,只要有同步任务,就必须先让同步任务走完,才可以走下面的代码,不管你是什么队列

- (void)GCDDemo2
{dispatch_queue_t concurrentqQueue = dispatch_queue_create(@"并行队列", DISPATCH_QUEUE_CONCURRENT);NSLog(@"111111");dispatch_sync(concurrentqQueue, ^{NSLog(@"222222");});NSLog(@"3333");//打印顺序为 1、2、3
}//或者
- (void)GCDDemo3
{dispatch_queue_t serialQueue = dispatch_queue_create(@"串行队列", DISPATCH_QUEUE_SERIAL);NSLog(@"111111");dispatch_sync(serialQueue, ^{NSLog(@"222222");});NSLog(@"3333");//打印顺序为 1、2、3
}

3.1.并行队列+ 异步任务, 执行顺序都是132. 

- (void)GCDDemo2
{dispatch_queue_t concurrentqQueue = dispatch_queue_create(@"并行队列", DISPATCH_QUEUE_CONCURRENT);NSLog(@"111111");dispatch_async(concurrentqQueue, ^{NSLog(@"222222");});NSLog(@"3333");//打印顺序为 1、3、2. 并行队列,可以多个任务一起执行,异步任务耗时,所以2没走完,先走3
}

3.2.串行队列+ 异步任务, 执行顺序都是132.  

- (void)GCDDemo2
{dispatch_queue_t serialQueue = dispatch_queue_create(@"串行队列", DISPATCH_QUEUE_SERIAL);NSLog(@"111111");dispatch_async(serialQueue, ^{NSLog(@"222222");});NSLog(@"3333");//打印顺序为1、3、2//串行对列,理论上是1、2、3.按顺序打印,但是因为2是异步任务,耗时操作且不会阻塞线程,所以先打印3.然后再打印2. (2是执行了的,但是由于是耗时,所以没有执行完毕,没有打印,串行队列是按顺序执行的,这里望周知,执行顺序是1、2、3,但是打印顺序是1、3、2)
}

例4:

特例: 放入主队列就会崩溃,目前不知道啥原因. 按理说主队列也是串行对列.不应该崩溃,先留个笔记,稍后研究解答:

(PS:同步任务不能跟主线程一起使用,这两个搭配会造成死锁、崩溃)

- (void)GCDDemo2
{//dispatch_get_main_queue() 主队列,崩溃NSLog(@"111111");dispatch_async(dispatch_get_main_queue(), ^{NSLog(@"222222");//代码在这里崩溃了,可能是死锁,});NSLog(@"3333");//打印1之后,就crash了
}

相关文章:

iOS GCD的基本使用

一:什么是GCD GCD的全程是:Grand Central Dispatch, 直白的用汉语翻译就是:厉害的中枢调度器. GCD 是iOS 的多线程技术的实现方案,但是它并不是多线程技术,它是“并发解决技术”,是苹果公司研发的,会自动管理线程(这一段定义有点拗口,简单了解就行) GCD会自动管理线程的生命…...

如何设计开发RTSP直播播放器?

技术背景 我们在对接RTSP直播播放器相关技术诉求的时候&#xff0c;好多开发者&#xff0c;除了选用成熟的RTSP播放器外&#xff0c;还想知其然知其所以然&#xff0c;对RTSP播放器的整体开发有个基础的了解&#xff0c;方便方案之作和技术延伸。本文抛砖引玉&#xff0c;做个…...

Java基础系列-一文搞懂自定义排序

java自定义排序 自定义排序的理解&#xff1a; 我们首先看需求&#xff1a;一个二维数组 [[1,3],[8,10],[15,18],[2,6]] 我们的需求是根据集合&#xff08;二维数组取出来的数据&#xff09; 左边小的左边这种方式排序 例如1<8 排序方式就是[1,3],[8,10] 此时我们就需…...

扫普通链接二维码打开小程序

1. 2.新增规则&#xff08;注意下载文件到跟目录下&#xff0c;需要建个文件夹放下载的校验文件&#xff09; 3.发布 ps&#xff1a;发布后&#xff0c;只能访问正式版本。体验版本如果加了 测试链接http://xxx/xsc/10 那么http://xxx/xsc/aa.....应该都能访问 例如aa101 aa…...

计算机储存与分区

Disk partitioning 盘分区是在辅助储存上创建一个或多个区域&#xff0c;以便可以单独管理每个区域。而这些区域称为分区&#xff08;partition&#xff09;。这通常是在为新盘选择分区方案后&#xff0c;需要做的事。 MBR and GPT 分区方案&#xff08;分区表&#xff09;有…...

OpenCV之换脸技术:一场面部识别的奇妙之旅

在这个数字化与智能化并进的时代&#xff0c;图像处理技术日益成为连接现实与虚拟世界的桥梁。其中&#xff0c;换脸技术作为一项颇受欢迎且富有挑战性的应用&#xff0c;不仅让人惊叹于技术的魔力&#xff0c;更在娱乐、影视制作等领域展现了无限可能。今天&#xff0c;我们就…...

Linux学习笔记9 文件系统的基础

一、查看文件组织结构 Linux中一切都是文件。 Linux和Win的文件系统不是一个结构&#xff0c;Linux存在的根目录是所有目录的起点。 所有的存储空间和设备共享一个根目录&#xff0c;不同的磁盘块和分区挂载在其下&#xff0c;成为某个子目录的子目录&#xff0c;甚至设备也挂…...

Android OpenGL粒子特效

在本篇&#xff0c;我们将开启一个新的项目&#xff0c;探索粒子的世界。粒子是一种基本的图形元素&#xff0c;它们通常被表示为一组点。通过巧妙地组合一些基础的物理效果&#xff0c;我们能够创造出许多令人惊叹的视觉效果。想象一下&#xff0c;我们可以模拟一个水滴从喷泉…...

5 -《本地部署开源大模型》在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战

在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战 无论是在单机单卡&#xff08;一台机器上只有一块GPU&#xff09;还是单机多卡&#xff08;一台机器上有多块GPU&#xff09;的硬件配置上启动ChatGLM3-6B模型&#xff0c;其前置环境配置和项目文件是相同的。如果大家对配置过程还…...

dpkg:错误:另外一个进程已经为dpkg前端锁加锁

一、 问题描述 在新装ubuntu系统时&#xff0c;我们常常会遇见dpkg的错误&#xff0c;dpkg:错误:另外一个进程已经为dpkg前端锁加锁&#xff0c;如下图。 二、问题解决 方法一 先执行sudo rm /var/lib/dpkg/lock-frontend然后再继续安装软件包&#xff0c;如果出现问题dpkg:…...

基于SSM服装定制系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;服装类型管理&#xff0c;服装信息管理&#xff0c;服装定制管理&#xff0c;留言反馈&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xf…...

RK3588开发笔记-usb3.0 xhci-hcd控制器挂死问题解决

目录 前言 一、问题现象 二、问题分析 三、问题排查 总结 前言 在使用 RK3588 芯片进行开发的过程中,我遇到了 USB 3.0 xHCI-HCD 控制器外接5G通讯模块偶尔挂死的问题。这个问题导致 USB 设备失去响应,且不能恢复,需要重启整个系统才能恢复使用,针对该问题进行大量测试以…...

深入解析TCP/IP协议:网络通信的基石

1. 引言 TCP/IP 协议是现代计算机网络的核心&#xff0c;它为互联网上的设备提供了通信的基础。在网络通信中&#xff0c;TCP/IP 协议栈是无处不在的&#xff0c;无论是个人设备的浏览器请求&#xff0c;还是大型分布式系统的内部通信&#xff0c;都依赖于它的稳定、高效与可靠…...

基于微信小程序的汽车预约维修系统(lw+演示+源码+运行)

基于微信小程序的汽车预约维修系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的汽车预约维修系统的开发全过程。通过分析基于微信小程序的汽车预约维修系统管理的不足&#xff0c;创建了…...

wifi、热点密码破解 - python

乐子脚本&#xff0c;有点小慢&#xff0c;试过多线程&#xff0c;系统 wifi 连接太慢了&#xff0c;需要时间确认&#xff0c;多线程的话系统根本反应不过来。 也就可以试试破解别人的热点&#xff0c;一般都是 123456 这样的傻鸟口令 # coding:utf-8 import pywifi from pyw…...

bean的实例化2024年10月17日

跟不上为基础 1.你的java学习路线 2. 3.课程 注解的装配 contoller调用service用的是注解装配...

告别ELK,APO提供基于ClickHouse开箱即用的高效日志方案——APO 0.6.0发布

ELK一直是日志领域的主流产品&#xff0c;但是ElasticSearch的成本很高&#xff0c;查询效果随着数据量的增加越来越慢。业界已经有很多公司&#xff0c;比如滴滴、B站、Uber、Cloudflare都已经使用ClickHose作为ElasticSearch的替代品&#xff0c;都取得了不错的效果&#xff…...

Excel使用技巧:定位Ctrl+G +公式+原位填充 Ctrl+Enter快速填充数据(处理合并单元格)

Excel的正确用法&#xff1a; Excel是个数据库&#xff0c;不要随意合并单元格。 数据输入的时候一定要按照行列输入&#xff0c;中间不要留空&#xff0c;不然就没有关联。 定位CtrlG 公式原位填充 CtrlEnter快速填充数据 如果把合并的单元格 取消合并&#xff0c;只有第一…...

JAVA学习-练习试用Java实现“成绩归类”

问题&#xff1a; 编写程序&#xff0c;输入一批学生的成绩&#xff0c;遇0或负数则输入结束&#xff0c;要求统计并输出优秀&#xff08;大于85&#xff09;、通过&#xff08;60&#xff5e;84&#xff09;和不及格&#xff08;小于60&#xff09;的学生人数。 示例 &#x…...

【Hive】7-拉链表的设计与实现

拉链表的设计与实现 数据同步问题 背景 例如&#xff1a;MySQL中有一张用户表: tb_user&#xff0c;每个用户注册完成以后&#xff0c;就会在用户表中新增该用户的信息&#xff0c;记录该用户的id、手机号码、用户名、性别、地址等信息。 每天都会有用户注册&#xff0c;产生…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...