iOS GCD(Grand Central Dispatch)
iOS 常用有三种线程管理方式,分别是 NSThread、GCD 与 NSOperation,现在我们先来了解一下其中的 GCD
串行与并行针对的是任务队列,而同步与异步,针对的则是线程。
Serial Queue + Sync 序列执行+同步
Serial Queue + Async 序列执行 + 异步 (按顺序)
Concurrent Queue + Sync 并发 + 同步 (按顺序)
Concurrent Queue + Async 并发 + 异步 (真正多线程)(不按顺序)
自定义串行队列有能力启动主线程和后台线程(只能启动一个后台线程),不会发生死锁。同步任务,会自动安排在主线程执行;遇到异步任务,自动安排在后台线程执行,所以不会死锁。
DispatchWorkItem 可添加 item 到队列中
//1. 只带尾随闭包
let item1 = DispatchWorkItem {print("item1")
}//2. 指定qos(执行优先级)或flags(特殊行为标记)
let item2 = DispatchWorkItem(qos: .userInteractive, flags: .barrier) {print("item2")
}
DispatchQueue
-
Main queue (串行队列) 仅能运行在主线程上
let mainQueue = DispatchQueue.main
-
Global queue(并行队列 Concurrent)
let globalQueue = DispatchQueue.global()
-
Custom queue(默认串行)
//串行队列,label名字随便取 let serialQueue = DispatchQueue(label: "test")//并行队列 let concurrentQueue = DispatchQueue(label: "test", attributes: .concurrent)
添加任务
异步
let mainQueue = DispatchQueue.main
mainQueue.async(execute: item1)let globalQueue = DispatchQueue.global()
globalQueue.async(execute: item1)let serialQueue = DispatchQueue(label: "serial")
serialQueue.async(execute: item1)let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent)
concurrentQueue.async(execute: item1)
同步
let mainQueue = DispatchQueue.main
mainQueue.sync(execute: item1) // 必定引起死锁let globalQueue = DispatchQueue.global()
globalQueue.sync(execute: item1)let serialQueue = DispatchQueue(label: "serial")
serialQueue.sync(execute: item1)let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent)
concurrentQueue.sync(execute: item1)
队列死锁,而不是线程死锁。主队列添加同步任务造成死锁的根本原因:
- 主队列只能运行在主线程。
- 主队列没有本事开启后台线程去干别的事情。
- 主队列一旦混入同步任务,就会跟已经存在的异步任务相互等待,导致死锁。
DispatchGroup
可把多个任务放到 group,方便管理。
当组内所有任务执行完成,GCD API 发送相应的通知。
- notify(): 不阻塞当前线程
- wait():阻塞当前线程
自定义串行队列一个异步或同步任务(A)嵌套另一个同步任务(B)会引起死锁。
A、B任务等效为:A1 -> B -> A2。
// 当前任务
let queue = DispatchQueue.init(label: "name")
queue.sync {// 死锁。同步要等外层执行后这里才能执行,而外层的执行需要这里先执行完。queue.sync {print(Thread.current) // 同步任务} // 当前任务print(Thread.current)
}
并行队列添加同步任务不会死锁,因为同步任务被安排在主线程执行,异步任务被安排在后台线程执行。
所有的同步任务最终都要安排到主线程运行,主线程运行长耗时任务会导致界面严重卡顿。
// 这两种方式都会使界面卡顿(15s)
override func viewDidAppear(_ animated: Bool) {//1. 全局队列执行同步任务DispatchQueue.global().sync {sleep(15)//当前线程休眠15秒}//2. 主队列执行异步任务DispatchQueue.main.async {sleep(15)//当前线程休眠15秒}
}
GCD 正确做法:A、B都定义成异步任务,在并行队列中嵌套异步任务,最后切换到主队列去刷新UI
let queue = DispatchQueue(label: "com.apple.request", attributes: .concurrent)//异步执行
queue.async {print("开始请求数据 \(Date()) thread: \(Thread.current)")sleep(10)//模拟网络请求print("数据请求完成 \(Date()) thread: \(Thread.current)")//异步执行queue.async {print("开始处理数据 \(Date()) thread: \(Thread.current)")sleep(5)//模拟数据处理print("数据处理完成 \(Date()) thread: \(Thread.current)")//切换到主队列,刷新UIDispatchQueue.main.async {print("UI刷新成功 \(Date()) thread: \(Thread.current)")}}
}
DispatchQueue.main 自动生成的主队列对象,可获取
DispatchQueue.global
DispatchQueue() 默认是序列队列
DispatchQueue(.concurrent) 并发队列
同步任务都会被分配到主线程。
global、自定义 serial 队列、并发队列,都有能力把异步任务分配到子线程。serial 只能开启一个子线程(做并发任务足够了)。
同队列中,同步任务会等待前方任务执行完再执行。(先来先服务)
number 是队列标识,name 是线程标识,使用 serial 安排同步任务和异步任务,会将同步的分给主线程,把异步的分给后台某个匿名线程。
let queue = DispatchQueue.init(label: "hei")
queue.async { print(Thread.current)
}queue.sync {queue.async {print(Thread.current) } // 虽然比下面的 print 早,但是把这个异步任务发到另外线程这个过程需要时间。print(Thread.current)
}queue.async { print(Thread.current)
} queue.sync {print(Thread.current)
}// 结果
// <NSThread: 0x7fde7c806950>{number = 5, name = (null)}
// <_NSMainThread: 0x7fde7cb06570>{number = 1, name = main}
// <NSThread: 0x7fde7c806950>{number = 5, name = (null)}
// <NSThread: 0x7fde7c806950>{number = 5, name = (null)}
// <_NSMainThread: 0x7fde7cb06570>{number = 1, name = main}
如果 serial 队列嵌套同步任务将会死锁。
// 当前任务
let queue = DispatchQueue.init(label: "name")
queue.sync {// 死锁。同步要等外层执行后这里才能执行,而外层的执行需要这里先执行完。queue.sync {print(Thread.current) // 同步任务} // 当前任务print(Thread.current)
}
相关文章:
iOS GCD(Grand Central Dispatch)
iOS 常用有三种线程管理方式,分别是 NSThread、GCD 与 NSOperation,现在我们先来了解一下其中的 GCD 串行与并行针对的是任务队列,而同步与异步,针对的则是线程。 Serial Queue Sync 序列执行同步 Serial Queue Async 序列执…...

Cross-Entropy Loss(多分类损失函数)
文章目录 1. 网络输出output:score2. Cross-Entropy Loss(多分类损失函数) 1. 网络输出output:score 2. Cross-Entropy Loss(多分类损失函数) 先用softmax function把score 变成 probabilities。再用交叉熵损失函数来进行Loss的计算...

TP858 3BSE018138R1 具有高性能CPU的工业PC技术
TP858 3BSE018138R1 具有高性能CPU的工业PC技术 为了充分利用新电脑的扩展图形功能,如DirectX,Beckhoff Automation重新设计了TwinCAT automation软件套件中的Scope工具。这为TwinCAT用户在灵活的软件环境中提供了一系列令人印象深刻的测量技术。改进的…...

Observability:使用 OpenTelemetry 手动检测 .NET 应用程序
作者:David Hope 在快节奏的软件开发领域,尤其是在云原生领域,DevOps 和 SRE 团队日益成为应用程序稳定性和增长的重要合作伙伴。 DevOps 工程师不断优化软件交付,而 SRE 团队则充当应用程序可靠性、可扩展性和顶级性能的管理者。…...
生产事故:redis主从的坑
一、问题 昨天生产redis缩容,3主3从模式,重启了服务器,重启了redis; 结果今天发现生产服务报错了,连接不上redis。 排查发现,由于生产后台只配置了一个redis的ip,本来是主redis的ip的&#x…...
maven本地仓库有依赖包,还会远程下载的问题
maven本地仓库有依赖包,还会远程下载的问题 传送门...

动作捕捉系统处理单点多点丢点问题
在动作捕捉数据采集过程中,丢点是经常容易遇到的问题。NOKOV度量动作捕捉软件可以方便地解决丢点问题。 一、单点丢点的处理 如下图,已经采集了动捕数据。 查看是否有丢点,在形影软件左上角选择“窗口分割”,在下方分割出一个空…...

FIFO 位宽转换
从8位转32位 module tb_fifo();reg clk,rst; initial beginclk0;forever #4.545 clk~clk; end initial beginrst1;#9.09 rst0; endreg [31:0] cnts; always (posedge clk or posedge rst) beginif(rst)begincnts < 32d0;endelsebegincnts < cnts 1b1;end endreg […...

瑞明达:聚“追梦”之力,共圆“经济梦”
矢志不渝,笃行不怠,争当“一心一意同国行”的无悔“追梦人”。过往几年,国际形势风高浪急,国内环境复杂多变,在后疫情时代、经济恢复压力等多种超预期的因素冲击下,瑞明达团队全面贯彻落实国家发展政策&…...

UE5数字孪生制作(一) - QGIS 学习笔记
1.下载 QGIS是免费的GIS工具,下载地址: https://www.qgis.org/en/site/ 2.安装 - 转中文 按照步骤安装,完成后,在菜单 设置settings里,选择options,修改语言 确定后,需要重启下软件 3.学习视…...
STM32 使用HAL库,HAL_Delay()会卡死, 程序一直卡在 HAL_GetTick( ) 函数中(已解决)
今天遇到个很奇怪的问题, 不知道为什么, 单片机运行一会之后, 系统就没反应了, 经过调试发现, 系统卡在HAL_Delay()中了. 之前也遇到过这个问题后来把HAL_Delay 去掉了. 然后发现不行, 还是得有它.不然发串口数据发的太快会乱掉. 得慢点发. 然后调试到HAL_Delay()方法的内部发…...

Maven Repository使用
1.Maven Repository网站 https://mvnrepository.com/https://mvnrepository.com/ 2.查询需要的依赖 3.参考例子 <!-- https://mvnrepository.com/artifact/org.freeswitch.esl.client/org.freeswitch.esl.client --> <dependency> <groupId>org.freesw…...

智安网络|保护您的应用程序免受攻击:重要的安全强化措施
在今天的数字化时代,应用程序安全成为了企业和个人必须重视的重要领域。应用程序普遍存在的安全漏洞成为黑客们进行攻击的一个突破口。为了保护敏感数据和个人隐私,我们必须了解并实施一系列的关键措施来加固应用程序的安全性。 首先,一个关…...
python3.8 use async getting invalid sysntax
python3.8 use async getting invalid sysntax 加载fever-drqa时报错: File "/data/yangjun/fact/wikifact/scripts/search_module.py", line 2, in <module> from drq…...

Mac 解决 APP 快捷键冲突
打开 Mac 系统设置键盘->键盘快捷键->App快捷键->添加快捷键(加号)->标题需要和tab名称完全一致(包括中英文、标点符号等,如下图)设置快捷键即可 Reference: https://www.cnblogs.com/Questio…...

mysql之事务
(一)事务 1、事务是一种机制一个操作序列,包含了一组数据库的操作命令,所有命令都是一个整体,向系统提交或者撤销的操作,要么都执行,要么都不执行 2、不可分割的单位 (二…...

组件化npm包打包和使用
背景:本地环境对功能组件提取,开发环境下通过本地路径引用,发布模式下走npm包引用 1、项目下新建packages/HelloWorld文件夹,在此文件夹下运行终端 npm init 新建packages/HelloWorld/index.vue文件 新建packages/HelloWorld/ind…...

Windows 内置Linux子系统的配置(From WSL1 to WSL2)
目录 我是如何从WSL1转到WSL2的? WSL1与WSL2的功能区别: 配置下载源 SSH配置 优雅使用windows的Linux子系统 我是如何从WSL1转到WSL2的? 第一次安装的子系统是WSL1的,因为不能使用systemctl ,以及因为WSL1没有完整的Linux内核,所以使得WSL1很多命令…...
2023-11-03 android app TextView 滚动,ScrollView 之外的另外一种方法
一、布局xml文件中TextView 增加下面属性 android:maxLines "AN_INTEGER" android:scrollbars "vertical" 二、在java代码中添加下面代码,就可以滚动了。 m_TextView.setMovementMethod(new ScrollingMovementMethod())...

SAP 获取GOS附件清单及URL数据方法
很久没有更新了,断更了快两个月了,最近准备软考考试,刚考完不知道这次能不能通过 回归正题 SAP中很多业务中都是可以上传附件或者是上传URL的路径的,上传附件长时间会占用SAP的空间,使用GOS大多数都是采用上传URL的方式…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...